From 0992e1e96d8bcc21c4ebe8f92ab859a15b7f750d Mon Sep 17 00:00:00 2001 From: FireMasterK <20838718+FireMasterK@users.noreply.github.com> Date: Sat, 17 Jul 2021 04:26:41 +0530 Subject: [PATCH] Login and subscriptions. (#256) * WIP login and subscriptions. * Add a working feed and unsubscribe button. * Allow importing subscriptions from Google Takeout, NewPipe and Invidious. --- package.json | 1 + src/components/Channel.vue | 44 ++++++++++- src/components/FeedPage.vue | 74 ++++++++++++++++++ src/components/ImportPage.vue | 129 ++++++++++++++++++++++++++++++++ src/components/LoginPage.vue | 66 ++++++++++++++++ src/components/Navigation.vue | 14 ++++ src/components/RegisterPage.vue | 66 ++++++++++++++++ src/main.js | 23 ++++++ src/router/router.js | 20 +++++ yarn.lock | 12 +++ 10 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 src/components/FeedPage.vue create mode 100644 src/components/ImportPage.vue create mode 100644 src/components/LoginPage.vue create mode 100644 src/components/RegisterPage.vue diff --git a/package.json b/package.json index 39f7fdf2..49e2e2d6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "dompurify": "^2.3.0", "hotkeys-js": "^3.8.7", "mux.js": "^5.12.2", + "javascript-time-ago": "^2.3.8", "register-service-worker": "^1.7.1", "shaka-player": "3.2.0", "uikit": "3.7.0", diff --git a/src/components/Channel.vue b/src/components/Channel.vue index fc30cd1e..8ba6dd19 100644 --- a/src/components/Channel.vue +++ b/src/components/Channel.vue @@ -6,6 +6,16 @@

{{ channel.description }}

+ +
@@ -28,6 +38,7 @@ export default { data() { return { channel: null, + subscribed: false, }; }, mounted() { @@ -40,6 +51,21 @@ export default { window.removeEventListener("scroll", this.handleScroll); }, methods: { + async fetchSubscribedStatus() { + this.fetchJson( + this.apiUrl() + "/subscribed", + { + channelId: this.channel.id, + }, + { + headers: { + Authorization: this.getAuthToken(), + }, + }, + ).then(json => { + this.subscribed = json.subscribed; + }); + }, async fetchChannel() { const url = this.apiUrl() + "/" + this.$route.params.path + "/" + this.$route.params.channelId; return await this.fetchJson(url); @@ -48,7 +74,10 @@ export default { this.fetchChannel() .then(data => (this.channel = data)) .then(() => { - if (!this.channel.error) document.title = this.channel.name + " - Piped"; + if (!this.channel.error) { + document.title = this.channel.name + " - Piped"; + if (this.authenticated) this.fetchSubscribedStatus(); + } }); }, handleScroll() { @@ -65,6 +94,19 @@ export default { }); } }, + subscribeHandler() { + this.fetchJson(this.apiUrl() + (this.subscribed ? "/unsubscribe" : "/subscribe"), null, { + method: "POST", + body: JSON.stringify({ + channelId: this.channel.id, + }), + headers: { + Authorization: this.getAuthToken(), + "Content-Type": "application/json", + }, + }); + this.subscribed = !this.subscribed; + }, }, components: { ErrorHandler, diff --git a/src/components/FeedPage.vue b/src/components/FeedPage.vue new file mode 100644 index 00000000..390efee8 --- /dev/null +++ b/src/components/FeedPage.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/components/ImportPage.vue b/src/components/ImportPage.vue new file mode 100644 index 00000000..f898cd70 --- /dev/null +++ b/src/components/ImportPage.vue @@ -0,0 +1,129 @@ + + + diff --git a/src/components/LoginPage.vue b/src/components/LoginPage.vue new file mode 100644 index 00000000..3be179e8 --- /dev/null +++ b/src/components/LoginPage.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue index b154e006..5f923608 100644 --- a/src/components/Navigation.vue +++ b/src/components/Navigation.vue @@ -25,6 +25,15 @@
  • Preferences
  • +
  • + Login +
  • +
  • + Register +
  • +
  • + Feed +
  • @@ -60,6 +69,11 @@ export default { suggestionsVisible: false, }; }, + computed: { + shouldShowLogin(_this) { + return _this.getAuthToken() == null; + }, + }, methods: { onKeyUp(e) { if (e.key === "Enter") { diff --git a/src/components/RegisterPage.vue b/src/components/RegisterPage.vue new file mode 100644 index 00000000..afb4bc60 --- /dev/null +++ b/src/components/RegisterPage.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/main.js b/src/main.js index 2df74d7e..c7333d1a 100644 --- a/src/main.js +++ b/src/main.js @@ -34,6 +34,14 @@ import App from "./App.vue"; import DOMPurify from "dompurify"; +import TimeAgo from "javascript-time-ago"; + +import en from "javascript-time-ago/locale/en"; + +TimeAgo.addDefaultLocale(en); + +const timeAgo = new TimeAgo("en-US"); + import("./registerServiceWorker"); const mixin = { @@ -136,6 +144,18 @@ const mixin = { window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; return theme; }, + getAuthToken() { + return this.getPreferenceString("authToken" + this.hashCode(this.apiUrl())); + }, + hashCode(s) { + return s.split("").reduce(function(a, b) { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + }, + timeAgo(time) { + return timeAgo.format(time); + }, }, computed: { backgroundColor() { @@ -153,6 +173,9 @@ const mixin = { darkMode() { return this.getEffectiveTheme() !== "light"; }, + authenticated(_this) { + return _this.getAuthToken() !== undefined; + }, }, }; diff --git a/src/router/router.js b/src/router/router.js index 132a388a..70d7c487 100644 --- a/src/router/router.js +++ b/src/router/router.js @@ -29,6 +29,26 @@ const routes = [ path: "/:path(channel|user|c)/:channelId/:videos?", component: () => import("../components/Channel.vue"), }, + { + path: "/login", + name: "Login", + component: () => import("../components/LoginPage.vue"), + }, + { + path: "/register", + name: "Register", + component: () => import("../components/RegisterPage.vue"), + }, + { + path: "/feed", + name: "Feed", + component: () => import("../components/FeedPage.vue"), + }, + { + path: "/import", + name: "Import", + component: () => import("../components/ImportPage.vue"), + }, ]; const router = createRouter({ diff --git a/yarn.lock b/yarn.lock index 91cb28d7..01f98123 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5186,6 +5186,13 @@ javascript-stringify@^2.0.1: resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== +javascript-time-ago@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/javascript-time-ago/-/javascript-time-ago-2.3.8.tgz#7e1cd94a770987cc00db82e60e655d3efdd25629" + integrity sha512-ahVSuInQC6iJtwy/XsburOc6JMsI0OI/84b3nAhtMlDhCm9g4Py+zuiPASnt02B4GkaURqWtiyw98ce0ICAZYQ== + dependencies: + relative-time-format "^1.0.5" + js-message@1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/js-message/-/js-message-1.0.7.tgz#fbddd053c7a47021871bb8b2c95397cc17c20e47" @@ -7196,6 +7203,11 @@ relateurl@0.2.x: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= +relative-time-format@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/relative-time-format/-/relative-time-format-1.0.5.tgz#3fb7c76ae39156afe0a3a7ff0cb7bf30aa0f0fb6" + integrity sha512-MAgx/YKcUQYJpIaWcfetPstElnWf26JxVis4PirdwVrrymFdbxyCSm6yENpfB1YuwFbtHSHksN3aBajVNxk10Q== + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"