feeds-fun 1.21.6 → 1.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/App.vue +2 -2
- package/src/components/EntryForList.vue +3 -3
- package/src/components/OPMLUpload.vue +21 -10
- package/src/components/page_footer/Footer.vue +4 -1
- package/src/components/page_header/ExternalLinks.vue +3 -4
- package/src/components/side_pannel/CollapseButton.vue +0 -1
- package/src/components/tags/FilterTag.vue +4 -4
- package/src/components/tags/TagsFilter.vue +2 -2
- package/src/css/inputs.css +21 -0
- package/src/layouts/SidePanelLayout.vue +19 -28
- package/src/logic/api.ts +279 -158
- package/src/logic/enums.ts +10 -0
- package/src/logic/events.ts +20 -12
- package/src/logic/settings.ts +4 -23
- package/src/logic/types.ts +36 -0
- package/src/main.ts +1 -54
- package/src/router/index.ts +0 -6
- package/src/stores/entries.ts +4 -4
- package/src/stores/globalSettings.ts +3 -11
- package/src/stores/globalState.ts +107 -9
- package/src/values/SocialLink.vue +8 -4
- package/src/views/CRMView.vue +1 -1
- package/src/views/FeedsView.vue +1 -1
- package/src/views/MainView.vue +51 -15
- package/src/views/PublicCollectionView.vue +8 -3
- package/src/views/SettingsView.vue +5 -6
- package/vite.config.ts +0 -13
- package/src/components/SupertokensLogin.vue +0 -141
- package/src/stores/supertokens.ts +0 -144
- package/src/views/AuthView.vue +0 -77
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-if="globalState.isLoggedIn">
|
|
3
|
-
<h3 class="">You have already logged in</h3>
|
|
4
|
-
<button
|
|
5
|
-
class="text-blue-600 hover:text-blue-800 text-xl pt-0"
|
|
6
|
-
@click.prevent="goToWorkspace()"
|
|
7
|
-
>Go To Feeds ⇒</button
|
|
8
|
-
>
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
<div v-else>
|
|
12
|
-
<h2 class="my-0">Single e-mail to log in</h2>
|
|
13
|
-
<template v-if="!requested">
|
|
14
|
-
<p class="text-center">We'll send you an email with a login link, no password required.</p>
|
|
15
|
-
|
|
16
|
-
<form
|
|
17
|
-
@submit.prevent="login()"
|
|
18
|
-
class="w-full flex justify-center">
|
|
19
|
-
<input
|
|
20
|
-
class="ffun-input flex-grow p-1 mr-2"
|
|
21
|
-
type="email"
|
|
22
|
-
v-model="email"
|
|
23
|
-
required
|
|
24
|
-
placeholder="me@example.com" />
|
|
25
|
-
<button
|
|
26
|
-
class="ffun-form-button"
|
|
27
|
-
type="submit"
|
|
28
|
-
>Log In</button
|
|
29
|
-
>
|
|
30
|
-
</form>
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<template v-else>
|
|
34
|
-
<p class="">
|
|
35
|
-
Login link was sent to <strong>{{ email }}</strong>
|
|
36
|
-
|
|
37
|
-
<a
|
|
38
|
-
class="ml-1"
|
|
39
|
-
@click.prevent="onChangeEmail()"
|
|
40
|
-
>change</a
|
|
41
|
-
>
|
|
42
|
-
</p>
|
|
43
|
-
|
|
44
|
-
<button
|
|
45
|
-
v-if="!counting"
|
|
46
|
-
type="button"
|
|
47
|
-
class="btn btn-primary ffun-form-button">
|
|
48
|
-
<span @click.prevent="resend()">Resend email</span>
|
|
49
|
-
</button>
|
|
50
|
-
|
|
51
|
-
<vue-countdown
|
|
52
|
-
v-else
|
|
53
|
-
:time="supertokens.allowResendAfter"
|
|
54
|
-
@end="onCountdownEnd"
|
|
55
|
-
class=""
|
|
56
|
-
v-slot="{totalSeconds}">
|
|
57
|
-
Resend in {{ totalSeconds }} seconds
|
|
58
|
-
</vue-countdown>
|
|
59
|
-
</template>
|
|
60
|
-
</div>
|
|
61
|
-
</template>
|
|
62
|
-
|
|
63
|
-
<script lang="ts" setup>
|
|
64
|
-
import {computed, ref, onMounted} from "vue";
|
|
65
|
-
import * as t from "@/logic/types";
|
|
66
|
-
import * as e from "@/logic/enums";
|
|
67
|
-
import * as api from "@/logic/api";
|
|
68
|
-
import {computedAsync} from "@vueuse/core";
|
|
69
|
-
import DOMPurify from "dompurify";
|
|
70
|
-
import {useEntriesStore} from "@/stores/entries";
|
|
71
|
-
import {useSupertokens} from "@/stores/supertokens";
|
|
72
|
-
import {useGlobalState} from "@/stores/globalState";
|
|
73
|
-
import {useRouter} from "vue-router";
|
|
74
|
-
import * as settings from "@/logic/settings";
|
|
75
|
-
const router = useRouter();
|
|
76
|
-
|
|
77
|
-
const globalState = useGlobalState();
|
|
78
|
-
|
|
79
|
-
const supertokens = useSupertokens();
|
|
80
|
-
|
|
81
|
-
const requested = ref(false);
|
|
82
|
-
|
|
83
|
-
const counting = ref(false);
|
|
84
|
-
|
|
85
|
-
const email = ref("");
|
|
86
|
-
|
|
87
|
-
async function afterEmailSend(success: boolean) {
|
|
88
|
-
if (success) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
window.alert("Something went wrong. Please try again.");
|
|
93
|
-
requested.value = false;
|
|
94
|
-
counting.value = false;
|
|
95
|
-
await supertokens.clearLoginAttempt();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function beforeEmailSend() {
|
|
99
|
-
requested.value = true;
|
|
100
|
-
counting.value = true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async function login() {
|
|
104
|
-
beforeEmailSend();
|
|
105
|
-
|
|
106
|
-
const success = await supertokens.sendMagicLink(email.value);
|
|
107
|
-
|
|
108
|
-
await afterEmailSend(success);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function resend() {
|
|
112
|
-
beforeEmailSend();
|
|
113
|
-
|
|
114
|
-
const success = await supertokens.resendMagicLink();
|
|
115
|
-
|
|
116
|
-
await afterEmailSend(success);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function onCountdownEnd() {
|
|
120
|
-
counting.value = false;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function onChangeEmail() {
|
|
124
|
-
requested.value = false;
|
|
125
|
-
await supertokens.clearLoginAttempt();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function goToWorkspace() {
|
|
129
|
-
router.push({name: e.MainPanelMode.Entries, params: {}});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
onMounted(async () => {
|
|
133
|
-
if (settings.authMode === settings.AuthMode.SingleUser) {
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
requested.value = await supertokens.hasInitialMagicLinkBeenSent();
|
|
138
|
-
});
|
|
139
|
-
</script>
|
|
140
|
-
|
|
141
|
-
<style scoped></style>
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import {ref, watch} from "vue";
|
|
2
|
-
import {useRouter} from "vue-router";
|
|
3
|
-
import {defineStore} from "pinia";
|
|
4
|
-
import {Timer} from "@/logic/timer";
|
|
5
|
-
import SuperTokens from "supertokens-web-js";
|
|
6
|
-
import Session from "supertokens-web-js/recipe/session";
|
|
7
|
-
import Passwordless from "supertokens-web-js/recipe/passwordless";
|
|
8
|
-
import * as passwordless from "supertokens-web-js/recipe/passwordless";
|
|
9
|
-
import {computedAsync} from "@vueuse/core";
|
|
10
|
-
|
|
11
|
-
export const useSupertokens = defineStore("supertokens", () => {
|
|
12
|
-
const isLoggedIn = ref<boolean | null>(null);
|
|
13
|
-
|
|
14
|
-
async function refresh() {
|
|
15
|
-
isLoggedIn.value = await Session.doesSessionExist();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const refresher = new Timer(refresh, 1000);
|
|
19
|
-
|
|
20
|
-
const allowResendAfter = ref(60 * 1000);
|
|
21
|
-
|
|
22
|
-
function init({
|
|
23
|
-
apiDomain,
|
|
24
|
-
apiBasePath,
|
|
25
|
-
appName,
|
|
26
|
-
resendAfter
|
|
27
|
-
}: {
|
|
28
|
-
apiDomain: string;
|
|
29
|
-
apiBasePath: string;
|
|
30
|
-
appName: string;
|
|
31
|
-
resendAfter: number;
|
|
32
|
-
}) {
|
|
33
|
-
allowResendAfter.value = resendAfter;
|
|
34
|
-
|
|
35
|
-
SuperTokens.init({
|
|
36
|
-
// enableDebugLogs: true,
|
|
37
|
-
appInfo: {
|
|
38
|
-
apiDomain: apiDomain,
|
|
39
|
-
apiBasePath: apiBasePath,
|
|
40
|
-
appName: appName
|
|
41
|
-
},
|
|
42
|
-
recipeList: [Session.init(), Passwordless.init()]
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
refresher.start();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function processError(err: any) {
|
|
49
|
-
await refresh();
|
|
50
|
-
|
|
51
|
-
if (err.isSuperTokensGeneralError === true) {
|
|
52
|
-
window.alert(err.message);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function sendMagicLink(email: string) {
|
|
57
|
-
try {
|
|
58
|
-
let response = await passwordless.createCode({
|
|
59
|
-
email
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return response.status === "OK";
|
|
63
|
-
} catch (err: any) {
|
|
64
|
-
await processError(err);
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function logout() {
|
|
70
|
-
await Session.signOut();
|
|
71
|
-
|
|
72
|
-
await passwordless.clearLoginAttemptInfo();
|
|
73
|
-
|
|
74
|
-
await refresh();
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function resendMagicLink() {
|
|
78
|
-
try {
|
|
79
|
-
let response = await passwordless.resendCode();
|
|
80
|
-
|
|
81
|
-
if (response.status === "OK") {
|
|
82
|
-
return true;
|
|
83
|
-
} else if (response.status === "RESTART_FLOW_ERROR") {
|
|
84
|
-
// this can happen if the user has already successfully logged in into
|
|
85
|
-
// another device whilst also trying to login to this one.
|
|
86
|
-
return false;
|
|
87
|
-
} else {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
} catch (err: any) {
|
|
91
|
-
await processError(err);
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async function hasInitialMagicLinkBeenSent() {
|
|
97
|
-
return (await passwordless.getLoginAttemptInfo()) !== undefined;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function handleMagicLinkClicked({
|
|
101
|
-
onSignUp,
|
|
102
|
-
onSignIn,
|
|
103
|
-
onSignFailed
|
|
104
|
-
}: {
|
|
105
|
-
onSignUp: () => void;
|
|
106
|
-
onSignIn: () => void;
|
|
107
|
-
onSignFailed: () => void;
|
|
108
|
-
}) {
|
|
109
|
-
try {
|
|
110
|
-
let response = await passwordless.consumeCode();
|
|
111
|
-
|
|
112
|
-
await refresh();
|
|
113
|
-
|
|
114
|
-
if (response.status === "OK") {
|
|
115
|
-
if (response.createdNewUser) {
|
|
116
|
-
await onSignUp();
|
|
117
|
-
} else {
|
|
118
|
-
await onSignIn();
|
|
119
|
-
}
|
|
120
|
-
} else {
|
|
121
|
-
await onSignFailed();
|
|
122
|
-
}
|
|
123
|
-
} catch (err: any) {
|
|
124
|
-
await processError(err);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function clearLoginAttempt() {
|
|
129
|
-
await passwordless.clearLoginAttemptInfo();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
allowResendAfter,
|
|
134
|
-
|
|
135
|
-
init,
|
|
136
|
-
sendMagicLink,
|
|
137
|
-
resendMagicLink,
|
|
138
|
-
isLoggedIn,
|
|
139
|
-
logout,
|
|
140
|
-
hasInitialMagicLinkBeenSent,
|
|
141
|
-
handleMagicLinkClicked,
|
|
142
|
-
clearLoginAttempt
|
|
143
|
-
};
|
|
144
|
-
});
|
package/src/views/AuthView.vue
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<wide-layout>
|
|
3
|
-
<div class="ffun-page-header">
|
|
4
|
-
<div class="ffun-page-header-center-block">
|
|
5
|
-
<page-header-external-links :show-api="false" />
|
|
6
|
-
</div>
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
|
-
<hr />
|
|
10
|
-
|
|
11
|
-
<main-block>
|
|
12
|
-
<h1 class="m-0 text-5xl">Feeds Fun</h1>
|
|
13
|
-
<p class="mt-2 text-2xl">Transparent Personalized News</p>
|
|
14
|
-
</main-block>
|
|
15
|
-
|
|
16
|
-
<main-block>
|
|
17
|
-
<div class="max-w-xl md:mx-auto ffun-info-good text-center mx-2">
|
|
18
|
-
<p>Checking login status...</p>
|
|
19
|
-
</div>
|
|
20
|
-
</main-block>
|
|
21
|
-
</wide-layout>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
|
-
<script lang="ts" setup>
|
|
25
|
-
import {computed, ref, onUnmounted, watch, provide, onBeforeMount} from "vue";
|
|
26
|
-
import {useRouter} from "vue-router";
|
|
27
|
-
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
28
|
-
import {useSupertokens} from "@/stores/supertokens";
|
|
29
|
-
import {useGlobalState} from "@/stores/globalState";
|
|
30
|
-
import {computedAsync} from "@vueuse/core";
|
|
31
|
-
import * as settings from "@/logic/settings";
|
|
32
|
-
|
|
33
|
-
const globalSettings = useGlobalSettingsStore();
|
|
34
|
-
const globalState = useGlobalState();
|
|
35
|
-
|
|
36
|
-
const supertokens = useSupertokens();
|
|
37
|
-
|
|
38
|
-
const router = useRouter();
|
|
39
|
-
|
|
40
|
-
provide("eventsViewName", "auth");
|
|
41
|
-
|
|
42
|
-
function goToWorkspace() {
|
|
43
|
-
router.push({name: globalSettings.mainPanelMode, params: {}});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function goToMain() {
|
|
47
|
-
router.push({name: "main", params: {}});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
onBeforeMount(async () => {
|
|
51
|
-
if (globalState.isLoggedIn) {
|
|
52
|
-
goToWorkspace();
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function onSignIn() {
|
|
57
|
-
goToWorkspace();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function onSignFailed() {
|
|
61
|
-
await supertokens.clearLoginAttempt();
|
|
62
|
-
goToMain();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (await supertokens.hasInitialMagicLinkBeenSent()) {
|
|
66
|
-
await supertokens.handleMagicLinkClicked({
|
|
67
|
-
onSignUp: onSignIn,
|
|
68
|
-
onSignIn: onSignIn,
|
|
69
|
-
onSignFailed: onSignFailed
|
|
70
|
-
});
|
|
71
|
-
} else {
|
|
72
|
-
goToMain();
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
</script>
|
|
76
|
-
|
|
77
|
-
<style></style>
|