feeds-fun 1.11.1 → 1.12.0
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 +1 -1
- package/src/components/DiscoveryForm.vue +5 -2
- package/src/components/FeedForList.vue +19 -7
- package/src/components/{OpenaiTokensUsage.vue → TokensCost.vue} +19 -9
- package/src/components/UserSettingForNotification.vue +1 -1
- package/src/components/collections/Block.vue +97 -0
- package/src/components/collections/BlockItem.vue +45 -0
- package/src/components/collections/DetailedItem.vue +115 -0
- package/src/components/collections/FeedItem.vue +62 -0
- package/src/components/collections/Notification.vue +11 -0
- package/src/components/collections/SubscribingProgress.vue +41 -0
- package/src/components/collections/Warning.vue +70 -0
- package/src/components/notifications/ApiKey.vue +42 -0
- package/src/components/notifications/Block.vue +61 -0
- package/src/components/{NotificationCreateRuleHelp.vue → notifications/CreateRuleHelp.vue} +2 -2
- package/src/layouts/SidePanelLayout.vue +0 -2
- package/src/logic/api.ts +31 -7
- package/src/logic/types.ts +108 -11
- package/src/main.ts +26 -12
- package/src/stores/collections.ts +53 -0
- package/src/stores/feeds.ts +48 -0
- package/src/style.css +17 -9
- package/src/views/CollectionsView.vue +21 -4
- package/src/views/DiscoveryView.vue +6 -0
- package/src/views/FeedsView.vue +11 -12
- package/src/views/MainView.vue +7 -0
- package/src/views/NewsView.vue +3 -2
- package/src/views/SettingsView.vue +29 -21
- package/src/components/FeedsCollections.vue +0 -102
- package/src/components/NotificationCollections.vue +0 -7
- package/src/components/NotificationOpenaiApiKey.vue +0 -28
- package/src/components/Notifications.vue +0 -43
package/package.json
CHANGED
|
@@ -59,6 +59,9 @@
|
|
|
59
59
|
import * as api from "@/logic/api";
|
|
60
60
|
import {computedAsync} from "@vueuse/core";
|
|
61
61
|
import {useEntriesStore} from "@/stores/entries";
|
|
62
|
+
import {useFeedsStore} from "@/stores/feeds";
|
|
63
|
+
|
|
64
|
+
const feedsStore = useFeedsStore();
|
|
62
65
|
|
|
63
66
|
const search = ref("");
|
|
64
67
|
|
|
@@ -91,10 +94,10 @@
|
|
|
91
94
|
return feeds;
|
|
92
95
|
}, null);
|
|
93
96
|
|
|
94
|
-
async function addFeed(url:
|
|
97
|
+
async function addFeed(url: t.URL) {
|
|
95
98
|
adding.value = true;
|
|
96
99
|
|
|
97
|
-
await
|
|
100
|
+
await feedsStore.subscribe(url);
|
|
98
101
|
|
|
99
102
|
addedFeeds.value[url] = true;
|
|
100
103
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<a
|
|
7
7
|
href="#"
|
|
8
8
|
class="ffun-normal-link"
|
|
9
|
-
@click.prevent="unsubscribe()">
|
|
9
|
+
@click.prevent="feedsStore.unsubscribe(feed.id)">
|
|
10
10
|
remove
|
|
11
11
|
</a>
|
|
12
12
|
</div>
|
|
@@ -53,9 +53,22 @@
|
|
|
53
53
|
class="ffun-normal-link"
|
|
54
54
|
:value="feed.url"
|
|
55
55
|
:text="purifiedTitle" />
|
|
56
|
+
|
|
57
|
+
<template v-if="feed.collectionIds.length > 0">
|
|
58
|
+
<span v-for="(collectionId, index) in feed.collectionIds">
|
|
59
|
+
<template v-if="collectionId in collections.collections">
|
|
60
|
+
<br />
|
|
61
|
+
Collections:
|
|
62
|
+
<span class="text-green-700 font-bold">{{ collections.collections[collectionId].name }}</span
|
|
63
|
+
><span v-if="index < feed.collectionIds.length - 1">, </span>
|
|
64
|
+
</template>
|
|
65
|
+
</span>
|
|
66
|
+
</template>
|
|
56
67
|
<template v-if="globalSettings.showFeedsDescriptions">
|
|
57
68
|
<br />
|
|
58
|
-
<div
|
|
69
|
+
<div class="max-w-3xl flex-1 bg-slate-50 border-2 rounded p-4">
|
|
70
|
+
<div v-html="purifiedDescription" />
|
|
71
|
+
</div>
|
|
59
72
|
</template>
|
|
60
73
|
</div>
|
|
61
74
|
</div>
|
|
@@ -69,8 +82,12 @@
|
|
|
69
82
|
import {computedAsync} from "@vueuse/core";
|
|
70
83
|
import DOMPurify from "dompurify";
|
|
71
84
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
85
|
+
import {useFeedsStore} from "@/stores/feeds";
|
|
86
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
72
87
|
|
|
73
88
|
const globalSettings = useGlobalSettingsStore();
|
|
89
|
+
const feedsStore = useFeedsStore();
|
|
90
|
+
const collections = useCollectionsStore();
|
|
74
91
|
|
|
75
92
|
const properties = defineProps<{feed: t.Feed}>();
|
|
76
93
|
|
|
@@ -94,9 +111,4 @@
|
|
|
94
111
|
}
|
|
95
112
|
return DOMPurify.sanitize(properties.feed.description);
|
|
96
113
|
});
|
|
97
|
-
|
|
98
|
-
async function unsubscribe() {
|
|
99
|
-
await api.unsubscribe({feedId: properties.feed.id});
|
|
100
|
-
globalSettings.updateDataVersion();
|
|
101
|
-
}
|
|
102
114
|
</script>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<tr>
|
|
3
3
|
<td>{{ period }}</td>
|
|
4
|
-
<td style="text-align: right">{{
|
|
5
|
-
<td style="text-align: right">{{
|
|
6
|
-
<td style="text-align: right">{{
|
|
4
|
+
<td style="text-align: right">{{ cost_used }}</td>
|
|
5
|
+
<td style="text-align: right">{{ cost_reserved }}</td>
|
|
6
|
+
<td style="text-align: right">{{ cost_total }}</td>
|
|
7
7
|
<td style="text-align: right">{{ percents }}%</td>
|
|
8
8
|
</tr>
|
|
9
9
|
</template>
|
|
@@ -24,20 +24,18 @@
|
|
|
24
24
|
|
|
25
25
|
globalSettings.mainPanelMode = e.MainPanelMode.Settings;
|
|
26
26
|
|
|
27
|
-
const openAIUsage = computedAsync(async () => {
|
|
28
|
-
return await api.getResourceHistory({kind: "openai_tokens"});
|
|
29
|
-
}, null);
|
|
30
|
-
|
|
31
27
|
const period = computed(() => {
|
|
32
28
|
return properties.usage.intervalStartedAt.toLocaleString("default", {month: "long", year: "numeric"});
|
|
33
29
|
});
|
|
34
30
|
|
|
31
|
+
const k = 2;
|
|
32
|
+
|
|
35
33
|
const percents = computed(() => {
|
|
36
34
|
if (globalSettings.userSettings == null) {
|
|
37
35
|
return "—";
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
const setting = globalSettings.userSettings["
|
|
38
|
+
const setting = globalSettings.userSettings["max_tokens_cost_in_month"];
|
|
41
39
|
|
|
42
40
|
if (!setting) {
|
|
43
41
|
return "—";
|
|
@@ -54,7 +52,19 @@
|
|
|
54
52
|
return "—";
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
return ((total / limit) * 100).toFixed(
|
|
55
|
+
return ((total / limit) * 100).toFixed(k);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const cost_used = computed(() => {
|
|
59
|
+
return properties.usage.used.toFixed(k);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const cost_reserved = computed(() => {
|
|
63
|
+
return properties.usage.reserved.toFixed(k);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const cost_total = computed(() => {
|
|
67
|
+
return properties.usage.total().toFixed(k);
|
|
58
68
|
});
|
|
59
69
|
</script>
|
|
60
70
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<form @submit.prevent="subscribe">
|
|
4
|
+
<collections-block-item
|
|
5
|
+
v-for="collectionId in collections.collectionsOrder"
|
|
6
|
+
v-model="selectedCollections"
|
|
7
|
+
:collectionId="collectionId"
|
|
8
|
+
:selectedCollections="selectedCollections" />
|
|
9
|
+
|
|
10
|
+
<button
|
|
11
|
+
type="submit"
|
|
12
|
+
class="ffun-form-button"
|
|
13
|
+
>Subscribe</button
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
<button
|
|
17
|
+
type="button"
|
|
18
|
+
class="ffun-form-button ml-2"
|
|
19
|
+
@click.prevent="router.push({name: e.MainPanelMode.Collections, params: {}})"
|
|
20
|
+
>Explore Feeds Library
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<user-setting-for-notification
|
|
24
|
+
class="ml-2"
|
|
25
|
+
kind="hide_message_about_adding_collections"
|
|
26
|
+
button-text="Hide this message" />
|
|
27
|
+
</form>
|
|
28
|
+
|
|
29
|
+
<collections-subscribing-progress
|
|
30
|
+
:loading="loading"
|
|
31
|
+
:loaded="loaded"
|
|
32
|
+
:error="error" />
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script lang="ts" setup>
|
|
37
|
+
import {useRouter, RouterLink, RouterView} from "vue-router";
|
|
38
|
+
import {computed, ref, watch} from "vue";
|
|
39
|
+
import type * as t from "@/logic/types";
|
|
40
|
+
import * as e from "@/logic/enums";
|
|
41
|
+
import * as api from "@/logic/api";
|
|
42
|
+
import {computedAsync} from "@vueuse/core";
|
|
43
|
+
import DOMPurify from "dompurify";
|
|
44
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
45
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
46
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
47
|
+
|
|
48
|
+
const router = useRouter();
|
|
49
|
+
|
|
50
|
+
const loading = ref(false);
|
|
51
|
+
const loaded = ref(false);
|
|
52
|
+
const error = ref(false);
|
|
53
|
+
|
|
54
|
+
const globalSettings = useGlobalSettingsStore();
|
|
55
|
+
|
|
56
|
+
const collections = useCollectionsStore();
|
|
57
|
+
|
|
58
|
+
const selectedCollections = ref<t.CollectionId[]>([]);
|
|
59
|
+
|
|
60
|
+
// fill selectedCollections in case collections are already loaded
|
|
61
|
+
selectedCollections.value.push(...collections.collectionsOrder);
|
|
62
|
+
|
|
63
|
+
// fill selectedCollections in case collections are not loaded yet
|
|
64
|
+
watch(
|
|
65
|
+
() => collections.collectionsOrder,
|
|
66
|
+
(newOrder) => {
|
|
67
|
+
selectedCollections.value.push(...newOrder);
|
|
68
|
+
},
|
|
69
|
+
{once: true}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
async function subscribe() {
|
|
73
|
+
loading.value = true;
|
|
74
|
+
loaded.value = false;
|
|
75
|
+
error.value = false;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
await api.subscribeToCollections({
|
|
79
|
+
collectionsIds: selectedCollections.value
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
loading.value = false;
|
|
83
|
+
loaded.value = true;
|
|
84
|
+
error.value = false;
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error(e);
|
|
87
|
+
|
|
88
|
+
loading.value = false;
|
|
89
|
+
loaded.value = false;
|
|
90
|
+
error.value = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
globalSettings.updateDataVersion();
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<style scoped></style>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<input
|
|
4
|
+
class="ffun-checkbox align-top m-1"
|
|
5
|
+
type="checkbox"
|
|
6
|
+
:id="collection.id"
|
|
7
|
+
:name="collection.name"
|
|
8
|
+
:value="collection.id"
|
|
9
|
+
v-model="model"
|
|
10
|
+
checked />
|
|
11
|
+
<label
|
|
12
|
+
class="ml-2"
|
|
13
|
+
:for="collection.id">
|
|
14
|
+
<div class="inline-block">
|
|
15
|
+
<span class="text-green-700 font-bold">{{ collection.name }}</span> [feeds: {{ collection.feedsNumber }}]
|
|
16
|
+
<p class="">{{ collection.description }}</p>
|
|
17
|
+
</div>
|
|
18
|
+
</label>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script lang="ts" setup>
|
|
23
|
+
import {computed, ref} from "vue";
|
|
24
|
+
import type * as t from "@/logic/types";
|
|
25
|
+
import * as e from "@/logic/enums";
|
|
26
|
+
import * as api from "@/logic/api";
|
|
27
|
+
import {computedAsync} from "@vueuse/core";
|
|
28
|
+
import DOMPurify from "dompurify";
|
|
29
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
30
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
31
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
32
|
+
|
|
33
|
+
const properties = defineProps<{
|
|
34
|
+
collectionId: t.CollectionId;
|
|
35
|
+
selectedCollections: t.CollectionId[];
|
|
36
|
+
}>();
|
|
37
|
+
|
|
38
|
+
const model = defineModel();
|
|
39
|
+
|
|
40
|
+
const collections = useCollectionsStore();
|
|
41
|
+
|
|
42
|
+
const collection = computed(() => collections.collections[properties.collectionId]);
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<style scoped></style>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<h3>{{ collection.name }}</h3>
|
|
4
|
+
<p class="">{{ collection.description }}</p>
|
|
5
|
+
|
|
6
|
+
<div v-if="showFeeds">
|
|
7
|
+
<div
|
|
8
|
+
v-for="feed in feeds"
|
|
9
|
+
:key="feed.url"
|
|
10
|
+
class="mb-2 pb-2 collection-feed-block">
|
|
11
|
+
<collections-feed-item :feed="feed" />
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<button
|
|
16
|
+
@click.prevent="subscribe"
|
|
17
|
+
class="ffun-form-button mr-2">
|
|
18
|
+
<template v-if="collection.feedsNumber === 1"> Subscribe to 1 feed </template>
|
|
19
|
+
|
|
20
|
+
<template v-else> Subscribe to all {{ collection.feedsNumber }} feeds </template>
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<button
|
|
24
|
+
v-if="!showFeeds"
|
|
25
|
+
@click.prevent="show"
|
|
26
|
+
class="ffun-form-button"
|
|
27
|
+
>Show feeds</button
|
|
28
|
+
>
|
|
29
|
+
|
|
30
|
+
<button
|
|
31
|
+
v-if="showFeeds"
|
|
32
|
+
@click.prevent="hide"
|
|
33
|
+
class="ffun-form-button"
|
|
34
|
+
>Hide feeds</button
|
|
35
|
+
>
|
|
36
|
+
|
|
37
|
+
<collections-subscribing-progress
|
|
38
|
+
:loading="loading"
|
|
39
|
+
:loaded="loaded"
|
|
40
|
+
:error="error" />
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script lang="ts" setup>
|
|
45
|
+
import {computed, ref} from "vue";
|
|
46
|
+
import type * as t from "@/logic/types";
|
|
47
|
+
import * as e from "@/logic/enums";
|
|
48
|
+
import * as api from "@/logic/api";
|
|
49
|
+
import {computedAsync} from "@vueuse/core";
|
|
50
|
+
import DOMPurify from "dompurify";
|
|
51
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
52
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
53
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
54
|
+
|
|
55
|
+
const properties = defineProps<{
|
|
56
|
+
collectionId: t.CollectionId;
|
|
57
|
+
}>();
|
|
58
|
+
|
|
59
|
+
const globalSettings = useGlobalSettingsStore();
|
|
60
|
+
|
|
61
|
+
const collections = useCollectionsStore();
|
|
62
|
+
|
|
63
|
+
const collection = computed(() => collections.collections[properties.collectionId]);
|
|
64
|
+
|
|
65
|
+
const loading = ref(false);
|
|
66
|
+
const loaded = ref(false);
|
|
67
|
+
const error = ref(false);
|
|
68
|
+
const showFeeds = ref(false);
|
|
69
|
+
|
|
70
|
+
async function subscribe() {
|
|
71
|
+
loading.value = true;
|
|
72
|
+
loaded.value = false;
|
|
73
|
+
error.value = false;
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await api.subscribeToCollections({
|
|
77
|
+
collectionsIds: [properties.collectionId]
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
loading.value = false;
|
|
81
|
+
loaded.value = true;
|
|
82
|
+
error.value = false;
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error(e);
|
|
85
|
+
|
|
86
|
+
loading.value = false;
|
|
87
|
+
loaded.value = false;
|
|
88
|
+
error.value = true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
globalSettings.updateDataVersion();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function show() {
|
|
95
|
+
showFeeds.value = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function hide() {
|
|
99
|
+
showFeeds.value = false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const feeds = computedAsync(
|
|
103
|
+
async () => {
|
|
104
|
+
return await collections.getFeeds({collectionId: properties.collectionId});
|
|
105
|
+
},
|
|
106
|
+
[],
|
|
107
|
+
{lazy: true}
|
|
108
|
+
);
|
|
109
|
+
</script>
|
|
110
|
+
|
|
111
|
+
<style scoped>
|
|
112
|
+
.collection-feed-block:not(:last-child) {
|
|
113
|
+
border-bottom-width: 1px;
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex">
|
|
3
|
+
<div class="flex-shrink-0 w-16 text-right pr-1">
|
|
4
|
+
<a
|
|
5
|
+
href="#"
|
|
6
|
+
v-if="!subscribed"
|
|
7
|
+
@click.prevent.stop="feedsStore.subscribe(feed.url)"
|
|
8
|
+
class="text-blue-700"
|
|
9
|
+
>subscribe</a
|
|
10
|
+
>
|
|
11
|
+
|
|
12
|
+
<span
|
|
13
|
+
v-else
|
|
14
|
+
class="text-green-700 cursor-default"
|
|
15
|
+
>subscribed</span
|
|
16
|
+
>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="flex-shrink-0 w-8 text-right pr-1">
|
|
20
|
+
<favicon-element
|
|
21
|
+
:url="feed.url"
|
|
22
|
+
class="w-4 h-4 align-text-bottom mx-1 inline" />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div class="flex-grow">
|
|
26
|
+
<strong>{{ feed.title }}</strong>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="flex">
|
|
31
|
+
<div class="flex-shrink-0 w-16 pr-1"> </div>
|
|
32
|
+
|
|
33
|
+
<div class="max-w-3xl flex-1 bg-slate-50 border-2 rounded p-4">
|
|
34
|
+
<p>{{ feed.description }}</p>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script lang="ts" setup>
|
|
40
|
+
import {computed, ref} from "vue";
|
|
41
|
+
import type * as t from "@/logic/types";
|
|
42
|
+
import * as e from "@/logic/enums";
|
|
43
|
+
import * as api from "@/logic/api";
|
|
44
|
+
import {computedAsync} from "@vueuse/core";
|
|
45
|
+
import DOMPurify from "dompurify";
|
|
46
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
47
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
48
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
49
|
+
import {useFeedsStore} from "@/stores/feeds";
|
|
50
|
+
|
|
51
|
+
const feedsStore = useFeedsStore();
|
|
52
|
+
|
|
53
|
+
const properties = defineProps<{
|
|
54
|
+
feed: t.CollectionFeedInfo;
|
|
55
|
+
}>();
|
|
56
|
+
|
|
57
|
+
const globalSettings = useGlobalSettingsStore();
|
|
58
|
+
|
|
59
|
+
const subscribed = computed(() => properties.feed.id in feedsStore.feeds);
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<style scoped></style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ffun-info-attention">
|
|
3
|
+
<h3>It looks like there's nothing to read!</h3>
|
|
4
|
+
<p
|
|
5
|
+
>But don't worry — we've prepared some ready-to-use thematic collections just for you. All the feeds in them are
|
|
6
|
+
fully tagged free of charge.</p
|
|
7
|
+
>
|
|
8
|
+
<p>Subscribe to some and enjoy the full power of Feeds Fun!</p>
|
|
9
|
+
<collections-block />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<p
|
|
4
|
+
v-if="loading"
|
|
5
|
+
class="ffun-info-attention"
|
|
6
|
+
>Subscribing...</p
|
|
7
|
+
>
|
|
8
|
+
|
|
9
|
+
<p
|
|
10
|
+
v-if="loaded"
|
|
11
|
+
class="ffun-info-good"
|
|
12
|
+
>Feeds added!</p
|
|
13
|
+
>
|
|
14
|
+
|
|
15
|
+
<p
|
|
16
|
+
v-if="error"
|
|
17
|
+
class="ffun-info-bad"
|
|
18
|
+
>Unknown error occurred! Please, try later.</p
|
|
19
|
+
>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script lang="ts" setup>
|
|
24
|
+
import {computed, ref} from "vue";
|
|
25
|
+
import type * as t from "@/logic/types";
|
|
26
|
+
import * as e from "@/logic/enums";
|
|
27
|
+
import * as api from "@/logic/api";
|
|
28
|
+
import {computedAsync} from "@vueuse/core";
|
|
29
|
+
import DOMPurify from "dompurify";
|
|
30
|
+
import {useEntriesStore} from "@/stores/entries";
|
|
31
|
+
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
32
|
+
import {useCollectionsStore} from "@/stores/collections";
|
|
33
|
+
|
|
34
|
+
const properties = defineProps<{
|
|
35
|
+
loading: boolean;
|
|
36
|
+
loaded: boolean;
|
|
37
|
+
error: boolean;
|
|
38
|
+
}>();
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<style scoped></style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ffun-info-attention">
|
|
3
|
+
<h3>Check your feed URLs</h3>
|
|
4
|
+
|
|
5
|
+
<p
|
|
6
|
+
>Websites like
|
|
7
|
+
<a
|
|
8
|
+
href="https://reddit.com"
|
|
9
|
+
target="_blank"
|
|
10
|
+
>Reddit</a
|
|
11
|
+
>
|
|
12
|
+
or
|
|
13
|
+
<a
|
|
14
|
+
href="https://arxiv.org"
|
|
15
|
+
target="_blank"
|
|
16
|
+
>arXiv</a
|
|
17
|
+
>
|
|
18
|
+
provide multiple feeds by:</p
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
<ul>
|
|
22
|
+
<li
|
|
23
|
+
>Customizing news categories lists in URL (like
|
|
24
|
+
<code class="inline-block">https://site.com/feed/rss?category1+category2</code>) instead of using separate
|
|
25
|
+
URLs.</li
|
|
26
|
+
>
|
|
27
|
+
<li
|
|
28
|
+
>Supporting different feed formats (like <code class="inline-block">https://site.com/feed/rss</code> and
|
|
29
|
+
<code class="inline-block">https://site.com/feed/atom</code>).</li
|
|
30
|
+
>
|
|
31
|
+
</ul>
|
|
32
|
+
|
|
33
|
+
<p
|
|
34
|
+
>This can lead to the same news item appearing in multiple feeds, not being recognized as news from collections,
|
|
35
|
+
and being processed with your API key. We do our best to detect such news, but there are always exceptions.</p
|
|
36
|
+
>
|
|
37
|
+
|
|
38
|
+
<p><strong>To get the most from free tagging in collections:</strong></p>
|
|
39
|
+
|
|
40
|
+
<ul>
|
|
41
|
+
<li>Use specific, granular feed URLs.</li>
|
|
42
|
+
<li
|
|
43
|
+
>Add feeds directly from
|
|
44
|
+
<a
|
|
45
|
+
class="ffun-normal-link"
|
|
46
|
+
href="#"
|
|
47
|
+
@click.prevent="goToCollections()"
|
|
48
|
+
>collections</a
|
|
49
|
+
>
|
|
50
|
+
instead of using URLs from sites.</li
|
|
51
|
+
>
|
|
52
|
+
</ul>
|
|
53
|
+
|
|
54
|
+
<user-setting-for-notification
|
|
55
|
+
class=""
|
|
56
|
+
kind="hide_message_check_your_feed_urls"
|
|
57
|
+
button-text="Hide this message" />
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script lang="ts" setup>
|
|
62
|
+
import {useRouter} from "vue-router";
|
|
63
|
+
import * as e from "@/logic/enums";
|
|
64
|
+
|
|
65
|
+
const router = useRouter();
|
|
66
|
+
|
|
67
|
+
function goToCollections() {
|
|
68
|
+
router.push({name: e.MainPanelMode.Collections, params: {}});
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ffun-info-attention">
|
|
3
|
+
<p>
|
|
4
|
+
Please
|
|
5
|
+
<a
|
|
6
|
+
href="#"
|
|
7
|
+
@click.prevent="goToSettings()"
|
|
8
|
+
>set up</a
|
|
9
|
+
>
|
|
10
|
+
your own OpenAI and/or Gemini API keys to tag your personal feeds.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
Remember, Feeds Fun provides tags for feeds from
|
|
15
|
+
<a
|
|
16
|
+
href="#"
|
|
17
|
+
@click.prevent="goToCollections()"
|
|
18
|
+
>collections</a
|
|
19
|
+
>
|
|
20
|
+
for free. You do not need to set up your own API keys to have tags in news from collections.
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<user-setting-for-notification
|
|
24
|
+
kind="hide_message_about_setting_up_key"
|
|
25
|
+
button-text="Hide this message" />
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script lang="ts" setup>
|
|
30
|
+
import {useRouter} from "vue-router";
|
|
31
|
+
import * as e from "@/logic/enums";
|
|
32
|
+
|
|
33
|
+
const router = useRouter();
|
|
34
|
+
|
|
35
|
+
function goToCollections() {
|
|
36
|
+
router.push({name: e.MainPanelMode.Collections, params: {}});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function goToSettings() {
|
|
40
|
+
router.push({name: e.MainPanelMode.Settings, params: {}});
|
|
41
|
+
}
|
|
42
|
+
</script>
|