feeds-fun 1.11.0 → 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.
Files changed (33) hide show
  1. package/package.json +1 -1
  2. package/src/components/DiscoveryForm.vue +5 -2
  3. package/src/components/FeedForList.vue +19 -7
  4. package/src/components/{OpenaiTokensUsage.vue → TokensCost.vue} +19 -9
  5. package/src/components/UserSettingForNotification.vue +1 -1
  6. package/src/components/collections/Block.vue +97 -0
  7. package/src/components/collections/BlockItem.vue +45 -0
  8. package/src/components/collections/DetailedItem.vue +115 -0
  9. package/src/components/collections/FeedItem.vue +62 -0
  10. package/src/components/collections/Notification.vue +11 -0
  11. package/src/components/collections/SubscribingProgress.vue +41 -0
  12. package/src/components/collections/Warning.vue +70 -0
  13. package/src/components/notifications/ApiKey.vue +42 -0
  14. package/src/components/notifications/Block.vue +61 -0
  15. package/src/components/{NotificationCreateRuleHelp.vue → notifications/CreateRuleHelp.vue} +2 -2
  16. package/src/layouts/SidePanelLayout.vue +38 -7
  17. package/src/logic/api.ts +31 -7
  18. package/src/logic/settings.ts +6 -0
  19. package/src/logic/types.ts +108 -11
  20. package/src/main.ts +26 -12
  21. package/src/stores/collections.ts +53 -0
  22. package/src/stores/feeds.ts +48 -0
  23. package/src/style.css +20 -10
  24. package/src/views/CollectionsView.vue +21 -4
  25. package/src/views/DiscoveryView.vue +6 -0
  26. package/src/views/FeedsView.vue +11 -12
  27. package/src/views/MainView.vue +7 -0
  28. package/src/views/NewsView.vue +3 -2
  29. package/src/views/SettingsView.vue +29 -21
  30. package/src/components/FeedsCollections.vue +0 -102
  31. package/src/components/NotificationCollections.vue +0 -7
  32. package/src/components/NotificationOpenaiApiKey.vue +0 -28
  33. package/src/components/Notifications.vue +0 -43
@@ -2,9 +2,20 @@
2
2
  <side-panel-layout :reload-button="false">
3
3
  <template #main-header> Collections </template>
4
4
 
5
- <p> Try to subscribe for the feeds collections that we are preparing for you! </p>
5
+ <div class="ffun-info-attention">
6
+ <p
7
+ >We've prepared some ready-to-use thematic collections just for you. All the feeds in them are fully tagged
8
+ free of charge.</p
9
+ >
10
+ <p>Subscribe to some and enjoy the full power of Feeds Fun!</p>
11
+ </div>
6
12
 
7
- <feeds-collections />
13
+ <div
14
+ v-for="collectionId in collections.collectionsOrder"
15
+ :key="collectionId"
16
+ class="collection-block pb-4">
17
+ <collections-detailed-item :collectionId="collectionId" />
18
+ </div>
8
19
  </side-panel-layout>
9
20
  </template>
10
21
 
@@ -15,11 +26,17 @@
15
26
  import * as t from "@/logic/types";
16
27
  import * as e from "@/logic/enums";
17
28
  import {useGlobalSettingsStore} from "@/stores/globalSettings";
18
- import {useEntriesStore} from "@/stores/entries";
29
+ import {useCollectionsStore} from "@/stores/collections";
19
30
 
20
31
  const globalSettings = useGlobalSettingsStore();
21
32
 
33
+ const collections = useCollectionsStore();
34
+
22
35
  globalSettings.mainPanelMode = e.MainPanelMode.Collections;
23
36
  </script>
24
37
 
25
- <style></style>
38
+ <style scoped>
39
+ .collection-block:not(:last-child) {
40
+ border-bottom-width: 1px;
41
+ }
42
+ </style>
@@ -2,6 +2,12 @@
2
2
  <side-panel-layout :reload-button="false">
3
3
  <template #main-header> Discovery </template>
4
4
 
5
+ <notifications
6
+ :create-rule-help="false"
7
+ :api-key="false"
8
+ :collections-notification_="false"
9
+ :collections-warning_="true" />
10
+
5
11
  <h2>Lood feeds from an OPML file</h2>
6
12
 
7
13
  <opml-upload />
@@ -32,8 +32,10 @@
32
32
 
33
33
  <notifications
34
34
  v-if="sortedFeeds !== null"
35
- :openai-api-key="false"
36
- :collections="sortedFeeds === null || sortedFeeds.length == 0" />
35
+ :create-rule-help="false"
36
+ :api-key="false"
37
+ :collections-notification_="sortedFeeds === null || sortedFeeds.length == 0"
38
+ :collections-warning_="true" />
37
39
 
38
40
  <feeds-list
39
41
  v-if="sortedFeeds"
@@ -48,26 +50,23 @@
48
50
  import {computed, ref, onUnmounted, watch} from "vue";
49
51
  import {computedAsync} from "@vueuse/core";
50
52
  import {useGlobalSettingsStore} from "@/stores/globalSettings";
53
+ import {useFeedsStore} from "@/stores/feeds";
51
54
  import * as api from "@/logic/api";
52
55
  import type * as t from "@/logic/types";
53
56
  import * as e from "@/logic/enums";
54
57
 
55
58
  const globalSettings = useGlobalSettingsStore();
56
59
 
57
- globalSettings.mainPanelMode = e.MainPanelMode.Feeds;
60
+ const feedsStore = useFeedsStore();
58
61
 
59
- const feeds = computedAsync(async () => {
60
- // force refresh
61
- globalSettings.dataVersion;
62
- return await api.getFeeds();
63
- }, null);
62
+ globalSettings.mainPanelMode = e.MainPanelMode.Feeds;
64
63
 
65
64
  const sortedFeeds = computed(() => {
66
- if (!feeds.value) {
67
- return null;
68
- }
65
+ let sorted = Object.values(feedsStore.feeds);
69
66
 
70
- let sorted = feeds.value.slice();
67
+ if (sorted.length === 0) {
68
+ return [];
69
+ }
71
70
 
72
71
  const orderProperties = e.FeedsOrderProperties.get(globalSettings.feedsOrder);
73
72
 
@@ -18,6 +18,13 @@
18
18
  <li>Filter and sort news how you want ⇒ read only what you want.</li>
19
19
  </ul>
20
20
 
21
+ <h2>Curated collections of feeds</h2>
22
+
23
+ <ul class="list-disc list-inside text-left">
24
+ <li>We handpick the most interesting feeds into thematic collections.</li>
25
+ <li>Feeds in the collections are tagged for free.</li>
26
+ </ul>
27
+
21
28
  <h2>You are in control</h2>
22
29
 
23
30
  <ul class="list-disc list-inside text-left">
@@ -48,8 +48,9 @@
48
48
  <notifications
49
49
  v-if="entriesStore.loadedEntriesReport !== null"
50
50
  :create-rule-help="hasEntries && !hasRules"
51
- :openai-api-key="true"
52
- :collections="!hasEntries" />
51
+ :api-key="true"
52
+ :collections-notification_="!hasEntries"
53
+ :collections-warning_="false" />
53
54
 
54
55
  <entries-list
55
56
  :entriesIds="entriesReport"
@@ -14,47 +14,44 @@
14
14
 
15
15
  <hr />
16
16
 
17
- <template v-for="(value, kind) of globalSettings.userSettings">
17
+ <template v-for="kind of settingsOrder">
18
18
  <user-setting :kind="kind" />
19
19
  <hr />
20
20
  </template>
21
21
 
22
- <h2>OpenAI usage</h2>
22
+ <h3>API usage</h3>
23
23
 
24
- <p>Token usage for your OpenAI key per month.</p>
24
+ <p>Estimated tokens cost for your API keys usage per month.</p>
25
25
 
26
26
  <ul class="list-disc list-inside">
27
- <li> <strong>Used tokens</strong> — the number of tokens in processed requests. </li>
27
+ <li> <strong>Estimated Used USD</strong> — the estimated cost of tokens in processed requests. </li>
28
28
  <li>
29
- <strong>Reserved tokens</strong> — the number of tokens reserved for requests that currently are processing or
30
- were not processed correctly.
31
- </li>
32
- <li>
33
- <strong>Total tokens</strong> — the total number of tokens used in the month. Should be not less than the
34
- actual used tokens, but can be bigger because we reserve more tokens than actually use.
29
+ <strong>Estimated Reserved USD</strong> — the estimated cost of tokens reserved for requests that currently are
30
+ processing or were not processed correctly.
35
31
  </li>
32
+ <li> <strong>Estimated Total USD</strong> — the estimated total cost of tokens used in the month. </li>
36
33
  </ul>
37
34
 
38
- <p v-if="openAIUsage == null">Loading...</p>
35
+ <p v-if="tokensCostData == null">Loading...</p>
39
36
 
40
37
  <table
41
38
  v-else
42
39
  class="border border-gray-300 rounded-lg">
43
40
  <thead class="bg-slate-200">
44
41
  <tr>
45
- <th class="p-2">Period</th>
46
- <th class="p-2">Used tokens</th>
47
- <th class="p-2">Reserved tokens</th>
48
- <th class="p-2">Total tokens</th>
49
- <th class="p-2">% from current maximum</th>
42
+ <th class="w-32">Period</th>
43
+ <th class="w-48">Estimated Used USD </th>
44
+ <th class="w-48">Estimated Reserved USD</th>
45
+ <th class="w-48">Estimated Total USD</th>
46
+ <th class="w-48">% From Maximum</th>
50
47
  </tr>
51
48
  </thead>
52
49
  <tbody>
53
- <openai-tokens-usage
50
+ <tokens-cost
54
51
  :usage="usage"
55
- v-for="usage of openAIUsage" />
52
+ v-for="usage of tokensCostData" />
56
53
 
57
- <tr v-if="openAIUsage.length == 0">
54
+ <tr v-if="tokensCostData.length == 0">
58
55
  <td class="text-center">—</td>
59
56
  <td class="text-center">—</td>
60
57
  <td class="text-center">—</td>
@@ -78,8 +75,8 @@
78
75
 
79
76
  globalSettings.mainPanelMode = e.MainPanelMode.Settings;
80
77
 
81
- const openAIUsage = computedAsync(async () => {
82
- return await api.getResourceHistory({kind: "openai_tokens"});
78
+ const tokensCostData = computedAsync(async () => {
79
+ return await api.getResourceHistory({kind: "tokens_cost"});
83
80
  }, null);
84
81
 
85
82
  const userId = computed(() => {
@@ -89,6 +86,17 @@
89
86
 
90
87
  return globalSettings.info.userId;
91
88
  });
89
+
90
+ // TODO: refactor, this is the temporary code to display settings in the right order
91
+ const settingsOrder = [
92
+ "openai_api_key",
93
+ "gemini_api_key",
94
+ "max_tokens_cost_in_month",
95
+ "process_entries_not_older_than",
96
+ "hide_message_about_setting_up_key",
97
+ "hide_message_about_adding_collections",
98
+ "hide_message_check_your_feed_urls"
99
+ ];
92
100
  </script>
93
101
 
94
102
  <style></style>
@@ -1,102 +0,0 @@
1
- <template>
2
- <div>
3
- <form @submit.prevent="subscribe">
4
- <ul class="mb-1">
5
- <li v-for="item in collections">
6
- <input
7
- class="ffun-checkbox"
8
- type="checkbox"
9
- :id="item"
10
- :name="item"
11
- :value="item"
12
- v-model="selectedCollections"
13
- checked />
14
- <label
15
- class="ml-2"
16
- :for="item"
17
- >{{ item }}</label
18
- >
19
- </li>
20
- </ul>
21
-
22
- <button
23
- type="submit"
24
- class="ffun-form-button"
25
- >Subscribe</button
26
- >
27
- </form>
28
-
29
- <p
30
- v-if="loading"
31
- class="ffun-info-attention"
32
- >subscribing...</p
33
- >
34
-
35
- <p
36
- v-if="loaded"
37
- class="ffun-info-good"
38
- >Feeds added!</p
39
- >
40
-
41
- <p
42
- v-if="error"
43
- class="ffun-info-bad"
44
- >Unknown error occurred! Please, try later.</p
45
- >
46
- </div>
47
- </template>
48
-
49
- <script lang="ts" setup>
50
- import {computed, ref} from "vue";
51
- import type * as t from "@/logic/types";
52
- import * as e from "@/logic/enums";
53
- import * as api from "@/logic/api";
54
- import {computedAsync} from "@vueuse/core";
55
- import DOMPurify from "dompurify";
56
- import {useEntriesStore} from "@/stores/entries";
57
- import {useGlobalSettingsStore} from "@/stores/globalSettings";
58
-
59
- const loading = ref(false);
60
- const loaded = ref(false);
61
- const error = ref(false);
62
-
63
- const selectedCollections = ref<t.FeedsCollectionId[]>([]);
64
-
65
- const globalSettings = useGlobalSettingsStore();
66
-
67
- const collections = computedAsync(async () => {
68
- const collections = await api.getFeedsCollections();
69
-
70
- for (const collectionId of collections) {
71
- selectedCollections.value.push(collectionId);
72
- }
73
-
74
- return collections;
75
- });
76
-
77
- async function subscribe() {
78
- loading.value = true;
79
- loaded.value = false;
80
- error.value = false;
81
-
82
- try {
83
- await api.subscribeToFeedsCollections({
84
- collectionsIds: selectedCollections.value
85
- });
86
-
87
- loading.value = false;
88
- loaded.value = true;
89
- error.value = false;
90
- } catch (e) {
91
- console.error(e);
92
-
93
- loading.value = false;
94
- loaded.value = false;
95
- error.value = true;
96
- }
97
-
98
- globalSettings.updateDataVersion();
99
- }
100
- </script>
101
-
102
- <style scoped></style>
@@ -1,7 +0,0 @@
1
- <template>
2
- <div class="ffun-info-attention">
3
- <p>It looks like you have no news to read.</p>
4
- <p> Try to subscribe for the feeds collections that we are preparing for you! </p>
5
- <feeds-collections />
6
- </div>
7
- </template>
@@ -1,28 +0,0 @@
1
- <template>
2
- <div class="ffun-info-attention">
3
- <p>
4
- Because, for now, our service is free to use and OpenAI API costs money, we politely ask you to set up your own
5
- OpenAI API key.
6
- </p>
7
- <p>
8
- You can do this on the
9
- <a
10
- href="#"
11
- @click.prevent="router.push({name: e.MainPanelMode.Settings, params: {}})"
12
- >settings</a
13
- >
14
- page.
15
- </p>
16
-
17
- <user-setting-for-notification
18
- kind="openai_hide_message_about_setting_up_key"
19
- button-text="Hide this message" />
20
- </div>
21
- </template>
22
-
23
- <script lang="ts" setup>
24
- import {useRouter} from "vue-router";
25
- import * as e from "@/logic/enums";
26
-
27
- const router = useRouter();
28
- </script>
@@ -1,43 +0,0 @@
1
- <template>
2
- <notification-openai-api-key v-if="showOpenAIKeyNotification" />
3
- <notification-collections v-if="showCollectionsNotification" />
4
- <notification-create-rule-help v-if="showCreateRuleHelpNotification" />
5
- </template>
6
-
7
- <script lang="ts" setup>
8
- import {computed, ref, onUnmounted, watch} from "vue";
9
- import {useGlobalSettingsStore} from "@/stores/globalSettings";
10
-
11
- const properties = defineProps<{
12
- openaiApiKey: boolean;
13
- collections: boolean;
14
- createRuleHelp: boolean;
15
- }>();
16
-
17
- const globalSettings = useGlobalSettingsStore();
18
-
19
- const showApiKeyMessage = computed(() => {
20
- return (
21
- globalSettings.userSettings &&
22
- !globalSettings.userSettings.openai_api_key.value &&
23
- !globalSettings.userSettings.openai_hide_message_about_setting_up_key.value
24
- );
25
- });
26
-
27
- const showCollectionsNotification = computed(() => {
28
- return properties.collections;
29
- });
30
-
31
- const showCreateRuleHelpNotification = computed(() => {
32
- return !showCollectionsNotification.value && properties.createRuleHelp;
33
- });
34
-
35
- const showOpenAIKeyNotification = computed(() => {
36
- return (
37
- !showCollectionsNotification.value &&
38
- !showCreateRuleHelpNotification.value &&
39
- properties.openaiApiKey &&
40
- showApiKeyMessage.value
41
- );
42
- });
43
- </script>