@@ -27,6 +27,7 @@
|
||||
-webkit-font-feature-settings: "liga";
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-feature-settings: "liga";
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* poppins-500 - latin */
|
||||
|
||||
@@ -698,6 +698,7 @@ ol li {
|
||||
|
||||
.show-on-large-screen {
|
||||
display: inline-flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-response {
|
||||
|
||||
85
components/firebase/feeds.vue
Normal file
85
components/firebase/feeds.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<virtual-list
|
||||
v-if="fb.currentFeeds.length !== 0"
|
||||
class="virtual-list"
|
||||
:class="{ filled: fb.currentFeeds.length }"
|
||||
:size="56"
|
||||
:remain="Math.min(8, fb.currentFeeds.length)"
|
||||
>
|
||||
<ul v-for="feed in fb.currentFeeds" :key="feed.id">
|
||||
<div class="show-on-large-screen">
|
||||
<li>
|
||||
<input
|
||||
:aria-label="$t('label')"
|
||||
type="text"
|
||||
readonly
|
||||
:value="feed.label"
|
||||
:placeholder="$t('no_label')"
|
||||
class="bg-color"
|
||||
/>
|
||||
</li>
|
||||
<button class="icon" @click="saveFeed(feed)">
|
||||
<i class="material-icons">get_app</i>
|
||||
</button>
|
||||
<button class="icon" @click="deleteFeed(feed)">
|
||||
<i class="material-icons">delete</i>
|
||||
</button>
|
||||
</div>
|
||||
</ul>
|
||||
</virtual-list>
|
||||
<ul v-else>
|
||||
<li>
|
||||
<label class="info">{{ $t("empty") }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.virtual-list {
|
||||
max-height: calc(100vh - 288px);
|
||||
}
|
||||
|
||||
.bg-color {
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { fb } from "../../functions/fb";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VirtualList: () => import("vue-virtual-scroll-list")
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fb
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
deleteFeed(feed) {
|
||||
fb.deleteFeed(feed.id);
|
||||
this.$toast.error(this.$t("deleted"), {
|
||||
icon: "delete"
|
||||
});
|
||||
},
|
||||
saveFeed(feed) {
|
||||
const dataToWrite = JSON.stringify(feed.message, null, 2);
|
||||
const file = new Blob([dataToWrite], { type: "application/json" });
|
||||
const a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = (feed.label + " on " + Date()).replace(/\./g, "[dot]");
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
this.$toast.success(this.$t("download_started"), {
|
||||
icon: "done"
|
||||
});
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
55
components/firebase/inputform.vue
Normal file
55
components/firebase/inputform.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
<input
|
||||
:aria-label="$t('label')"
|
||||
type="text"
|
||||
autofocus
|
||||
v-model="message"
|
||||
:placeholder="$t('paste_a_collection')"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<input
|
||||
:aria-label="$t('label')"
|
||||
type="text"
|
||||
autofocus
|
||||
v-model="label"
|
||||
:placeholder="$t('label')"
|
||||
/>
|
||||
</li>
|
||||
<button
|
||||
class="icon"
|
||||
:disabled="!(this.message && this.label)"
|
||||
value="Save"
|
||||
@click="formPost"
|
||||
>
|
||||
<i class="material-icons">add</i>
|
||||
<span>Add</span>
|
||||
</button>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fb } from "../../functions/fb";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
message: null,
|
||||
label: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
formPost() {
|
||||
fb.writeFeeds(this.message, this.label);
|
||||
this.message = null;
|
||||
this.label = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
115
components/firebase/login.vue
Normal file
115
components/firebase/login.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<v-popover>
|
||||
<button class="icon" v-tooltip="$t('login_with')">
|
||||
<i class="material-icons">vpn_key</i>
|
||||
</button>
|
||||
<template slot="popover">
|
||||
<div>
|
||||
<button class="icon" @click="signInWithGoogle" v-close-popover>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="material-icons"
|
||||
>
|
||||
<path
|
||||
d="M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Google</span>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button class="icon" @click="signInWithGithub" v-close-popover>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="material-icons"
|
||||
>
|
||||
<path
|
||||
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
|
||||
/>
|
||||
</svg>
|
||||
<span>GitHub</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</v-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import firebase from "firebase/app";
|
||||
import { fb } from "../../functions/fb";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fb
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
signInWithGoogle() {
|
||||
const provider = new firebase.auth.GoogleAuthProvider();
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithPopup(provider)
|
||||
.then(res => {
|
||||
if (res.additionalUserInfo.isNewUser) {
|
||||
this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), {
|
||||
icon: "sync",
|
||||
duration: null,
|
||||
closeOnSwipe: false,
|
||||
action: {
|
||||
text: this.$t("yes"),
|
||||
onClick: (e, toastObject) => {
|
||||
fb.writeSettings("syncHistory", false);
|
||||
fb.writeSettings("syncCollections", true);
|
||||
this.$router.push({ path: "/settings" });
|
||||
toastObject.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
},
|
||||
signInWithGithub() {
|
||||
const provider = new firebase.auth.GithubAuthProvider();
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithPopup(provider)
|
||||
.then(res => {
|
||||
if (res.additionalUserInfo.isNewUser) {
|
||||
this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), {
|
||||
icon: "sync",
|
||||
duration: null,
|
||||
closeOnSwipe: false,
|
||||
action: {
|
||||
text: this.$t("yes"),
|
||||
onClick: (e, toastObject) => {
|
||||
fb.writeSettings("syncHistory", false);
|
||||
fb.writeSettings("syncCollections", true);
|
||||
this.$router.push({ path: "/settings" });
|
||||
toastObject.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -331,6 +331,7 @@ ol li {
|
||||
|
||||
<script>
|
||||
import { findStatusGroup } from "../pages/index";
|
||||
import { fb } from "../functions/fb";
|
||||
|
||||
const updateOnLocalStorage = (propertyName, property) =>
|
||||
window.localStorage.setItem(propertyName, JSON.stringify(property));
|
||||
@@ -341,11 +342,11 @@ export default {
|
||||
VirtualList: () => import("vue-virtual-scroll-list")
|
||||
},
|
||||
data() {
|
||||
const localStorageHistory = JSON.parse(
|
||||
window.localStorage.getItem("history")
|
||||
);
|
||||
return {
|
||||
history: localStorageHistory || [],
|
||||
history:
|
||||
fb.currentUser !== null
|
||||
? fb.currentHistory
|
||||
: JSON.parse(window.localStorage.getItem("history")) || [],
|
||||
filterText: "",
|
||||
showFilter: false,
|
||||
isClearingHistory: false,
|
||||
@@ -359,6 +360,10 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
filteredHistory() {
|
||||
this.history =
|
||||
fb.currentUser !== null
|
||||
? fb.currentHistory
|
||||
: JSON.parse(window.localStorage.getItem("history")) || [];
|
||||
return this.history.filter(entry => {
|
||||
const filterText = this.filterText.toLowerCase();
|
||||
return Object.keys(entry).some(key => {
|
||||
@@ -371,6 +376,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
clearHistory() {
|
||||
if (fb.currentUser !== null) {
|
||||
fb.clearHistory();
|
||||
}
|
||||
this.history = [];
|
||||
this.filterText = "";
|
||||
this.disableHistoryClearing();
|
||||
@@ -391,6 +399,9 @@ export default {
|
||||
);
|
||||
},
|
||||
deleteHistory(entry) {
|
||||
if (fb.currentUser !== null) {
|
||||
fb.deleteHistory(entry);
|
||||
}
|
||||
this.history.splice(this.history.indexOf(entry), 1);
|
||||
if (this.history.length === 0) {
|
||||
this.filterText = "";
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
match /{document=**} {
|
||||
allow read, write;
|
||||
allow read, write: if request.auth.uid != null;
|
||||
}
|
||||
// Make sure the uid of the requesting user matches name of the user
|
||||
// document. The wildcard expression {userId} makes the userId variable
|
||||
// available in rules.
|
||||
match /users/{userId} {
|
||||
allow read, update, delete: if request.auth.uid == userId;
|
||||
allow create: if request.auth.uid != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
165
functions/fb.js
Normal file
165
functions/fb.js
Normal file
@@ -0,0 +1,165 @@
|
||||
import firebase from "firebase/app";
|
||||
import "firebase/firestore";
|
||||
import "firebase/auth";
|
||||
|
||||
// Initialize Firebase, copied from cloud console
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM",
|
||||
authDomain: "postwoman-api.firebaseapp.com",
|
||||
databaseURL: "https://postwoman-api.firebaseio.com",
|
||||
projectId: "postwoman-api",
|
||||
storageBucket: "postwoman-api.appspot.com",
|
||||
messagingSenderId: "421993993223",
|
||||
appId: "1:421993993223:web:ec0baa8ee8c02ffa1fc6a2",
|
||||
measurementId: "G-ERJ6025CEB"
|
||||
};
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
|
||||
// a reference to the users collection
|
||||
const usersCollection = firebase.firestore().collection("users");
|
||||
|
||||
// the shared state object that any vue component
|
||||
// can get access to
|
||||
export const fb = {
|
||||
currentUser: {},
|
||||
currentFeeds: [],
|
||||
currentSettings: [],
|
||||
currentHistory: [],
|
||||
writeFeeds: async (message, label) => {
|
||||
const dt = {
|
||||
createdOn: new Date(),
|
||||
author: fb.currentUser.uid,
|
||||
author_name: fb.currentUser.displayName,
|
||||
author_image: fb.currentUser.photoURL,
|
||||
message,
|
||||
label
|
||||
};
|
||||
try {
|
||||
return usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("feeds")
|
||||
.add(dt);
|
||||
} catch (e) {
|
||||
return console.error("error inserting", dt, e);
|
||||
}
|
||||
},
|
||||
deleteFeed: id => {
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("feeds")
|
||||
.doc(id)
|
||||
.delete()
|
||||
.catch(e => console.error("error deleting", id, e));
|
||||
},
|
||||
writeSettings: async (setting, value) => {
|
||||
const st = {
|
||||
updatedOn: new Date(),
|
||||
author: fb.currentUser.uid,
|
||||
author_name: fb.currentUser.displayName,
|
||||
author_image: fb.currentUser.photoURL,
|
||||
name: setting,
|
||||
value
|
||||
};
|
||||
try {
|
||||
return usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("settings")
|
||||
.doc(setting)
|
||||
.set(st);
|
||||
} catch (e) {
|
||||
return console.error("error updating", st, e);
|
||||
}
|
||||
},
|
||||
writeHistory: async entry => {
|
||||
const hs = entry;
|
||||
try {
|
||||
return usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("history")
|
||||
.add(hs);
|
||||
} catch (e) {
|
||||
return console.error("error inserting", hs, e);
|
||||
}
|
||||
},
|
||||
deleteHistory: entry => {
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("history")
|
||||
.doc(entry.id)
|
||||
.delete()
|
||||
.catch(e => console.error("error deleting", entry, e));
|
||||
},
|
||||
clearHistory: () => {
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("history")
|
||||
.get()
|
||||
.then(({ docs }) => {
|
||||
docs.forEach(e => fb.deleteHistory(e));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// When a user logs in or out, save that in the store
|
||||
firebase.auth().onAuthStateChanged(user => {
|
||||
if (user) {
|
||||
fb.currentUser = user;
|
||||
fb.currentUser.providerData.forEach(profile => {
|
||||
let us = {
|
||||
updatedOn: new Date(),
|
||||
provider: profile.providerId,
|
||||
name: profile.displayName,
|
||||
email: profile.email,
|
||||
photoUrl: profile.photoURL,
|
||||
uid: profile.uid
|
||||
};
|
||||
try {
|
||||
usersCollection.doc(fb.currentUser.uid).set(us);
|
||||
} catch (e) {
|
||||
console.error("error updating", us, e);
|
||||
}
|
||||
});
|
||||
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("feeds")
|
||||
.orderBy("createdOn", "desc")
|
||||
.onSnapshot(feedsRef => {
|
||||
const feeds = [];
|
||||
feedsRef.forEach(doc => {
|
||||
const feed = doc.data();
|
||||
feed.id = doc.id;
|
||||
feeds.push(feed);
|
||||
});
|
||||
fb.currentFeeds = feeds;
|
||||
});
|
||||
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("settings")
|
||||
.onSnapshot(settingsRef => {
|
||||
const settings = [];
|
||||
settingsRef.forEach(doc => {
|
||||
const setting = doc.data();
|
||||
setting.id = doc.id;
|
||||
settings.push(setting);
|
||||
});
|
||||
fb.currentSettings = settings;
|
||||
});
|
||||
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("history")
|
||||
.onSnapshot(historyRef => {
|
||||
const history = [];
|
||||
historyRef.forEach(doc => {
|
||||
const entry = doc.data();
|
||||
entry.id = doc.id;
|
||||
history.push(entry);
|
||||
});
|
||||
fb.currentHistory = history;
|
||||
});
|
||||
} else {
|
||||
fb.currentUser = null;
|
||||
}
|
||||
});
|
||||
@@ -249,5 +249,15 @@ export default {
|
||||
extensions: "Extensions",
|
||||
extensions_info1: "Browser extension that simplifies access to Postwoman",
|
||||
extensions_info2: "Get Postwoman browser extension!",
|
||||
installed: "Installed"
|
||||
installed: "Installed",
|
||||
login_with: "Login with",
|
||||
logged_out: "Logged out",
|
||||
logout: "Logout",
|
||||
account: "Account",
|
||||
sync: "Sync",
|
||||
syncHistory: "History",
|
||||
syncCollections: "Collections",
|
||||
turn_on: "Turn on",
|
||||
login_first: "Login first",
|
||||
paste_a_collection: "Paste a Collection"
|
||||
};
|
||||
|
||||
@@ -237,6 +237,11 @@
|
||||
<div v-else-if="$route.path === '/settings'">
|
||||
<nav class="secondary-nav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#account" v-tooltip.right="$t('account')">
|
||||
<i class="material-icons">person</i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#theme" v-tooltip.right="$t('theme')">
|
||||
<i class="material-icons">brush</i>
|
||||
@@ -288,6 +293,46 @@
|
||||
>
|
||||
<i class="material-icons">offline_bolt</i>
|
||||
</button>
|
||||
<login v-if="!fb.currentUser" />
|
||||
<span v-if="fb.currentUser">
|
||||
<v-popover>
|
||||
<button
|
||||
class="icon"
|
||||
v-tooltip="
|
||||
(fb.currentUser.displayName ||
|
||||
'<label><i>Name not found</i></label>') +
|
||||
'<br>' +
|
||||
(fb.currentUser.email ||
|
||||
'<label><i>Email not found</i></label>')
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-if="fb.currentUser.photoURL"
|
||||
:src="fb.currentUser.photoURL"
|
||||
class="material-icons"
|
||||
/>
|
||||
<i v-else class="material-icons">account_circle</i>
|
||||
</button>
|
||||
<template slot="popover">
|
||||
<div>
|
||||
<nuxt-link :to="localePath('settings')" v-close-popover>
|
||||
<button class="icon">
|
||||
<i class="material-icons">settings</i>
|
||||
<span>
|
||||
{{ $t("settings") }}
|
||||
</span>
|
||||
</button>
|
||||
</nuxt-link>
|
||||
</div>
|
||||
<div>
|
||||
<button class="icon" @click="logout" v-close-popover>
|
||||
<i class="material-icons">exit_to_app</i>
|
||||
<span>{{ $t("logout") }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</v-popover>
|
||||
</span>
|
||||
<v-popover>
|
||||
<button class="icon" v-tooltip="$t('more')">
|
||||
<i class="material-icons">more_vert</i>
|
||||
@@ -620,10 +665,14 @@ import intializePwa from "../assets/js/pwa";
|
||||
import * as version from "../.postwoman/version.json";
|
||||
import { hasChromeExtensionInstalled } from "../functions/strategies/ChromeStrategy";
|
||||
|
||||
import firebase from 'firebase/app';
|
||||
import { fb } from '../functions/fb';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
logo: () => import("../components/logo"),
|
||||
modal: () => import("../components/modal")
|
||||
modal: () => import("../components/modal"),
|
||||
login: () => import("../components/firebase/login")
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -632,6 +681,21 @@ export default {
|
||||
"nuxt-link-exact-active": this.$route.path === path,
|
||||
"nuxt-link-active": this.$route.path === path
|
||||
};
|
||||
},
|
||||
|
||||
logout() {
|
||||
fb.currentUser = null;
|
||||
firebase
|
||||
.auth()
|
||||
.signOut()
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
this.$toast.info(this.$t("logged_out"), {
|
||||
icon: "vpn_key"
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -646,7 +710,8 @@ export default {
|
||||
showShortcuts: false,
|
||||
showSupport: false,
|
||||
firefoxExtInstalled: window.firefoxExtSendRequest,
|
||||
chromeExtInstalled: window.chrome && hasChromeExtensionInstalled()
|
||||
chromeExtInstalled: window.chrome && hasChromeExtensionInstalled(),
|
||||
fb
|
||||
};
|
||||
},
|
||||
|
||||
@@ -767,7 +832,7 @@ export default {
|
||||
|
||||
watch: {
|
||||
$route() {
|
||||
this.$toast.clear();
|
||||
// this.$toast.clear();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
994
package-lock.json
generated
994
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,11 +26,13 @@
|
||||
"@nuxtjs/sitemap": "^2.0.1",
|
||||
"@nuxtjs/toast": "^3.3.0",
|
||||
"ace-builds": "^1.4.8",
|
||||
"firebase": "^7.7.0",
|
||||
"graphql": "^14.5.8",
|
||||
"nuxt": "^2.11.0",
|
||||
"nuxt-i18n": "^6.4.1",
|
||||
"v-tooltip": "^2.0.2",
|
||||
"vue-virtual-scroll-list": "^1.4.4",
|
||||
"vuefire": "^2.2.1",
|
||||
"vuejs-auto-complete": "^0.9.0",
|
||||
"vuex-persist": "^2.2.0",
|
||||
"yargs-parser": "^16.1.0"
|
||||
|
||||
@@ -846,6 +846,26 @@
|
||||
<collections />
|
||||
</pw-section>
|
||||
</div>
|
||||
<input id="sync-tab" type="radio" name="side" />
|
||||
<label for="sync-tab">{{ $t("sync") }}</label>
|
||||
<div class="tab">
|
||||
<pw-section
|
||||
v-if="fb.currentUser"
|
||||
class="pink"
|
||||
label="Sync"
|
||||
ref="sync"
|
||||
>
|
||||
<inputform />
|
||||
<ballsfeed />
|
||||
</pw-section>
|
||||
<pw-section v-else>
|
||||
<ul>
|
||||
<li>
|
||||
<label>{{ $t("login_first") }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
</pw-section>
|
||||
</div>
|
||||
</section>
|
||||
</aside>
|
||||
|
||||
@@ -1136,6 +1156,7 @@ import parseTemplateString from "../functions/templating";
|
||||
import AceEditor from "../components/ace-editor";
|
||||
import { tokenRequest, oauthRedirect } from "../assets/js/oauth";
|
||||
import { sendNetworkRequest } from "../functions/network";
|
||||
import { fb } from "../functions/fb";
|
||||
|
||||
const statusCategories = [
|
||||
{
|
||||
@@ -1200,7 +1221,9 @@ export default {
|
||||
autocomplete: () => import("../components/autocomplete"),
|
||||
collections: () => import("../components/collections"),
|
||||
saveRequestAs: () => import("../components/collections/saveRequestAs"),
|
||||
Editor: AceEditor
|
||||
Editor: AceEditor,
|
||||
inputform: () => import("../components/firebase/inputform"),
|
||||
ballsfeed: () => import("../components/firebase/feeds")
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -1370,12 +1393,12 @@ export default {
|
||||
],
|
||||
showRequestModal: false,
|
||||
editRequest: {},
|
||||
|
||||
urlExcludes: {},
|
||||
responseBodyText: "",
|
||||
responseBodyType: "text",
|
||||
responseBodyMaxLines: 16,
|
||||
activeSidebar: true
|
||||
activeSidebar: true,
|
||||
fb
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -2106,6 +2129,11 @@ export default {
|
||||
star: false
|
||||
};
|
||||
this.$refs.historyComponent.addEntry(entry);
|
||||
if (fb.currentUser !== null) {
|
||||
if (fb.currentSettings[1].value) {
|
||||
fb.writeHistory(entry);
|
||||
}
|
||||
}
|
||||
})();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -2127,6 +2155,11 @@ export default {
|
||||
preRequestScript: this.preRequestScript
|
||||
};
|
||||
this.$refs.historyComponent.addEntry(entry);
|
||||
if (fb.currentUser !== null) {
|
||||
if (fb.currentSettings[1].value) {
|
||||
fb.writeHistory(entry);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
this.response.status = error.message;
|
||||
@@ -2139,7 +2172,7 @@ export default {
|
||||
icon: "help",
|
||||
duration: 8000,
|
||||
action: {
|
||||
text: "Settings",
|
||||
text: this.$t("yes"),
|
||||
onClick: (e, toastObject) => {
|
||||
this.$router.push({ path: "/settings" });
|
||||
}
|
||||
|
||||
@@ -1,5 +1,88 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<pw-section class="green" :label="$t('account')" ref="account">
|
||||
<ul>
|
||||
<li>
|
||||
<div v-if="fb.currentUser">
|
||||
<button class="icon">
|
||||
<img
|
||||
v-if="fb.currentUser.photoURL"
|
||||
:src="fb.currentUser.photoURL"
|
||||
class="material-icons"
|
||||
/>
|
||||
<i v-else class="material-icons">account_circle</i>
|
||||
<span>
|
||||
{{ fb.currentUser.displayName || "Name not found" }}
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button class="icon">
|
||||
<i class="material-icons">email</i>
|
||||
<span>
|
||||
{{ fb.currentUser.email || "Email not found" }}
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button class="icon" @click="logout">
|
||||
<i class="material-icons">exit_to_app</i>
|
||||
<span>{{ $t("logout") }}</span>
|
||||
</button>
|
||||
<br />
|
||||
<p v-for="setting in fb.currentSettings" :key="setting.id">
|
||||
<pw-toggle
|
||||
:key="setting.name"
|
||||
:on="setting.value"
|
||||
@change="toggleSettings(setting.name, setting.value)"
|
||||
>
|
||||
{{ $t(setting.name) + " " + $t("sync") }}
|
||||
{{ setting.value ? $t("enabled") : $t("disabled") }}
|
||||
</pw-toggle>
|
||||
</p>
|
||||
<p v-if="fb.currentSettings.length == 0">
|
||||
<button class="" @click="writeSettings">
|
||||
<i class="material-icons">sync</i>
|
||||
<span>{{ $t("turn_on") + " " + $t("sync") }}</span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<label>{{ $t("login_with") }}</label>
|
||||
<p>
|
||||
<button class="icon" @click="signInWithGoogle">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="material-icons"
|
||||
>
|
||||
<path
|
||||
d="M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Google</span>
|
||||
</button>
|
||||
<br />
|
||||
<button class="icon" @click="signInWithGithub">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
class="material-icons"
|
||||
>
|
||||
<path
|
||||
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
|
||||
/>
|
||||
</svg>
|
||||
<span>GitHub</span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</pw-section>
|
||||
|
||||
<pw-section class="cyan" :label="$t('theme')" ref="theme">
|
||||
<ul>
|
||||
<li>
|
||||
@@ -137,6 +220,9 @@
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
<script>
|
||||
import firebase from "firebase/app";
|
||||
import { fb } from "../functions/fb";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
"pw-section": () => import("../components/section"),
|
||||
@@ -238,7 +324,9 @@ export default {
|
||||
this.$store.state.postwoman.settings.PROXY_URL ||
|
||||
"https://postwoman.apollotv.xyz/",
|
||||
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || ""
|
||||
}
|
||||
},
|
||||
|
||||
fb
|
||||
};
|
||||
},
|
||||
|
||||
@@ -289,8 +377,88 @@ export default {
|
||||
toggleSetting(key) {
|
||||
this.settings[key] = !this.settings[key];
|
||||
this.$store.commit("postwoman/applySetting", [key, this.settings[key]]);
|
||||
},
|
||||
logout() {
|
||||
fb.currentUser = null;
|
||||
firebase
|
||||
.auth()
|
||||
.signOut()
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
this.$toast.info(this.$t("logged_out"), {
|
||||
icon: "vpn_key"
|
||||
});
|
||||
},
|
||||
signInWithGoogle() {
|
||||
const provider = new firebase.auth.GoogleAuthProvider();
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithPopup(provider)
|
||||
.then(res => {
|
||||
if (res.additionalUserInfo.isNewUser) {
|
||||
this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), {
|
||||
icon: "sync",
|
||||
duration: null,
|
||||
closeOnSwipe: false,
|
||||
action: {
|
||||
text: this.$t("yes"),
|
||||
onClick: (e, toastObject) => {
|
||||
fb.writeSettings("syncHistory", false);
|
||||
fb.writeSettings("syncCollections", true);
|
||||
this.$router.push({ path: "/settings" });
|
||||
toastObject.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
},
|
||||
signInWithGithub() {
|
||||
const provider = new firebase.auth.GithubAuthProvider();
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithPopup(provider)
|
||||
.then(res => {
|
||||
if (res.additionalUserInfo.isNewUser) {
|
||||
this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), {
|
||||
icon: "sync",
|
||||
duration: null,
|
||||
closeOnSwipe: false,
|
||||
action: {
|
||||
text: this.$t("yes"),
|
||||
onClick: (e, toastObject) => {
|
||||
fb.writeSettings("syncHistory", false);
|
||||
fb.writeSettings("syncCollections", true);
|
||||
this.$router.push({ path: "/settings" });
|
||||
toastObject.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.show(err.message || err, {
|
||||
icon: "error"
|
||||
});
|
||||
});
|
||||
},
|
||||
toggleSettings(s, v) {
|
||||
fb.writeSettings(s, !v);
|
||||
},
|
||||
writeSettings() {
|
||||
fb.writeSettings("syncHistory", false);
|
||||
fb.writeSettings("syncCollections", true);
|
||||
}
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.settings.THEME_COLOR = this.getActiveColor();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user