feeds-fun 1.17.1 → 1.18.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 +1 -1
- package/src/components/EntriesList.vue +11 -0
- package/src/components/EntryForList.vue +17 -6
- package/src/components/RuleForList.vue +2 -2
- package/src/components/RulesList.vue +18 -9
- package/src/components/TokensCost.vue +0 -2
- package/src/components/collections/DetailedItem.vue +9 -0
- package/src/components/collections/PublicIntro.vue +63 -0
- package/src/components/collections/PublicSelector.vue +43 -0
- package/src/components/main/Block.vue +1 -1
- package/src/components/main/Item.vue +1 -1
- package/src/components/notifications/LoadedOldNews.vue +47 -0
- package/src/components/page_header/ExternalLinks.vue +11 -6
- package/src/components/side_pannel/CollapseButton.vue +56 -0
- package/src/components/tags/EntryTag.vue +4 -3
- package/src/components/tags/FilterTag.vue +6 -3
- package/src/components/tags/RuleTag.vue +4 -3
- package/src/components/tags/TagsFilter.vue +17 -5
- package/src/css/panels.css +5 -5
- package/src/css/side_panel_layout.css +4 -0
- package/src/layouts/SidePanelLayout.vue +51 -26
- package/src/layouts/WideLayout.vue +0 -4
- package/src/logic/api.ts +23 -0
- package/src/logic/enums.ts +28 -12
- package/src/logic/events.ts +56 -8
- package/src/logic/tagsFilterState.ts +61 -1
- package/src/logic/types.ts +15 -2
- package/src/logic/utils.ts +104 -1
- package/src/main.ts +10 -0
- package/src/router/index.ts +16 -3
- package/src/stores/collections.ts +17 -1
- package/src/stores/entries.ts +154 -19
- package/src/stores/globalSettings.ts +11 -8
- package/src/views/AuthView.vue +3 -1
- package/src/views/CollectionsView.vue +13 -2
- package/src/views/DiscoveryView.vue +3 -1
- package/src/views/FeedsView.vue +3 -1
- package/src/views/MainView.vue +18 -1
- package/src/views/NewsView.vue +36 -97
- package/src/views/PublicCollectionView.vue +237 -0
- package/src/views/RulesView.vue +31 -29
- package/src/views/SettingsView.vue +3 -1
package/src/main.ts
CHANGED
|
@@ -38,6 +38,7 @@ import PageHeaderExternalLinks from "./components/page_header/ExternalLinks.vue"
|
|
|
38
38
|
import NotificationsApiKey from "./components/notifications/ApiKey.vue";
|
|
39
39
|
import NotificationsCreateRuleHelp from "./components/notifications/CreateRuleHelp.vue";
|
|
40
40
|
import Notifications from "./components/notifications/Block.vue";
|
|
41
|
+
import NotificationsLoadedOldNews from "./components/notifications/LoadedOldNews.vue";
|
|
41
42
|
|
|
42
43
|
import CollectionsNotification from "./components/collections/Notification.vue";
|
|
43
44
|
import CollectionsWarning from "./components/collections/Warning.vue";
|
|
@@ -46,6 +47,8 @@ import CollectionsBlockItem from "./components/collections/BlockItem.vue";
|
|
|
46
47
|
import CollectionsDetailedItem from "./components/collections/DetailedItem.vue";
|
|
47
48
|
import CollectionsSubscribingProgress from "./components/collections/SubscribingProgress.vue";
|
|
48
49
|
import CollectionsFeedItem from "./components/collections/FeedItem.vue";
|
|
50
|
+
import CollectionsPublicSelector from "./components/collections/PublicSelector.vue";
|
|
51
|
+
import CollectionsPublicIntro from "./components/collections/PublicIntro.vue";
|
|
49
52
|
|
|
50
53
|
import ScoreSelector from "./inputs/ScoreSelector.vue";
|
|
51
54
|
|
|
@@ -64,6 +67,8 @@ import MainNewsTitle from "./components/main/NewsTitle.vue";
|
|
|
64
67
|
import MainHeaderLine from "./components/main/HeaderLine.vue";
|
|
65
68
|
import MainBlock from "./components/main/Block.vue";
|
|
66
69
|
|
|
70
|
+
import SidePanelCollapseButton from "./components/side_pannel/CollapseButton.vue";
|
|
71
|
+
|
|
67
72
|
import WideLayout from "./layouts/WideLayout.vue";
|
|
68
73
|
import SidePanelLayout from "./layouts/SidePanelLayout.vue";
|
|
69
74
|
|
|
@@ -105,6 +110,7 @@ app.component("PageHeaderExternalLinks", PageHeaderExternalLinks);
|
|
|
105
110
|
app.component("NotificationsApiKey", NotificationsApiKey);
|
|
106
111
|
app.component("NotificationsCreateRuleHelp", NotificationsCreateRuleHelp);
|
|
107
112
|
app.component("Notifications", Notifications);
|
|
113
|
+
app.component("NotificationsLoadedOldNews", NotificationsLoadedOldNews);
|
|
108
114
|
|
|
109
115
|
app.component("CollectionsNotification", CollectionsNotification);
|
|
110
116
|
app.component("CollectionsWarning", CollectionsWarning);
|
|
@@ -113,6 +119,8 @@ app.component("CollectionsBlockItem", CollectionsBlockItem);
|
|
|
113
119
|
app.component("CollectionsDetailedItem", CollectionsDetailedItem);
|
|
114
120
|
app.component("CollectionsSubscribingProgress", CollectionsSubscribingProgress);
|
|
115
121
|
app.component("CollectionsFeedItem", CollectionsFeedItem);
|
|
122
|
+
app.component("CollectionsPublicSelector", CollectionsPublicSelector);
|
|
123
|
+
app.component("CollectionsPublicIntro", CollectionsPublicIntro);
|
|
116
124
|
|
|
117
125
|
app.component("ScoreSelector", ScoreSelector);
|
|
118
126
|
|
|
@@ -131,6 +139,8 @@ app.component("MainNewsTitle", MainNewsTitle);
|
|
|
131
139
|
app.component("MainHeaderLine", MainHeaderLine);
|
|
132
140
|
app.component("MainBlock", MainBlock);
|
|
133
141
|
|
|
142
|
+
app.component("SidePanelCollapseButton", SidePanelCollapseButton);
|
|
143
|
+
|
|
134
144
|
app.component("WideLayout", WideLayout);
|
|
135
145
|
app.component("SidePanelLayout", SidePanelLayout);
|
|
136
146
|
|
package/src/router/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import RulesView from "../views/RulesView.vue";
|
|
|
7
7
|
import DiscoveryView from "../views/DiscoveryView.vue";
|
|
8
8
|
import CollectionsView from "../views/CollectionsView.vue";
|
|
9
9
|
import SettingsView from "../views/SettingsView.vue";
|
|
10
|
+
import PublicCollectionView from "../views/PublicCollectionView.vue";
|
|
10
11
|
import * as e from "@/logic/enums";
|
|
11
12
|
|
|
12
13
|
// lazy view loading does not work with router.push function
|
|
@@ -31,12 +32,12 @@ const router = createRouter({
|
|
|
31
32
|
component: FeedsView
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
|
-
path: "/news",
|
|
35
|
+
path: "/news/:tags*",
|
|
35
36
|
name: e.MainPanelMode.Entries,
|
|
36
37
|
component: NewsView
|
|
37
38
|
},
|
|
38
39
|
{
|
|
39
|
-
path: "/rules",
|
|
40
|
+
path: "/rules/:tags*",
|
|
40
41
|
name: e.MainPanelMode.Rules,
|
|
41
42
|
component: RulesView
|
|
42
43
|
},
|
|
@@ -54,8 +55,20 @@ const router = createRouter({
|
|
|
54
55
|
path: "/settings",
|
|
55
56
|
name: e.MainPanelMode.Settings,
|
|
56
57
|
component: SettingsView
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
path: "/show/:collectionSlug/:tags*",
|
|
61
|
+
name: "public-collection",
|
|
62
|
+
component: PublicCollectionView
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
path: "/:pathMatch(.*)*",
|
|
66
|
+
redirect: "/"
|
|
57
67
|
}
|
|
58
|
-
]
|
|
68
|
+
],
|
|
69
|
+
scrollBehavior(to, from, savedPosition) {
|
|
70
|
+
return {top: 0};
|
|
71
|
+
}
|
|
59
72
|
});
|
|
60
73
|
|
|
61
74
|
export default router;
|
|
@@ -33,6 +33,10 @@ export const useCollectionsStore = defineStore("collectionsStore", () => {
|
|
|
33
33
|
return order;
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
const collectionsOrdered = computed(() => {
|
|
37
|
+
return collectionsOrder.value.map((id) => collections.value[id]);
|
|
38
|
+
});
|
|
39
|
+
|
|
36
40
|
async function getFeeds({collectionId}: {collectionId: t.CollectionId}) {
|
|
37
41
|
if (collectionId in feeds.value) {
|
|
38
42
|
return feeds.value[collectionId];
|
|
@@ -45,9 +49,21 @@ export const useCollectionsStore = defineStore("collectionsStore", () => {
|
|
|
45
49
|
return feeds.value[collectionId];
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
function getCollectionBySlug({slug}: {slug: t.CollectionSlug}) {
|
|
53
|
+
for (const collection of Object.values(collections.value)) {
|
|
54
|
+
if (collection.slug === slug) {
|
|
55
|
+
return collection;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
return {
|
|
49
63
|
collections,
|
|
50
64
|
collectionsOrder,
|
|
51
|
-
|
|
65
|
+
collectionsOrdered,
|
|
66
|
+
getFeeds,
|
|
67
|
+
getCollectionBySlug
|
|
52
68
|
};
|
|
53
69
|
});
|
package/src/stores/entries.ts
CHANGED
|
@@ -5,13 +5,21 @@ import _ from "lodash";
|
|
|
5
5
|
import * as t from "@/logic/types";
|
|
6
6
|
import * as e from "@/logic/enums";
|
|
7
7
|
import * as api from "@/logic/api";
|
|
8
|
+
import * as utils from "@/logic/utils";
|
|
8
9
|
import {Timer} from "@/logic/timer";
|
|
9
10
|
import {computedAsync} from "@vueuse/core";
|
|
10
11
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
11
12
|
import * as events from "@/logic/events";
|
|
13
|
+
import {useGlobalState} from "@/stores/globalState";
|
|
14
|
+
|
|
15
|
+
enum Mode {
|
|
16
|
+
News = "news",
|
|
17
|
+
PublicCollection = "public-collection"
|
|
18
|
+
}
|
|
12
19
|
|
|
13
20
|
export const useEntriesStore = defineStore("entriesStore", () => {
|
|
14
21
|
const globalSettings = useGlobalSettingsStore();
|
|
22
|
+
const globalState = useGlobalState();
|
|
15
23
|
|
|
16
24
|
const entries = ref<{[key: t.EntryId]: t.Entry}>({});
|
|
17
25
|
const requestedEntries = ref<{[key: t.EntryId]: boolean}>({});
|
|
@@ -20,17 +28,74 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
20
28
|
|
|
21
29
|
const canUndoMarkRead = computed(() => readHistory.value.length > 0);
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
const mode = ref<Mode | null>(null);
|
|
32
|
+
const modePublicCollectionSlug = ref<t.CollectionSlug | null>(null);
|
|
33
|
+
|
|
34
|
+
function setNewsMode() {
|
|
35
|
+
if (mode.value == Mode.News) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
mode.value = Mode.News;
|
|
40
|
+
|
|
41
|
+
globalSettings.updateDataVersion();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function setPublicCollectionMode(collectionSlug: t.CollectionSlug) {
|
|
45
|
+
if (mode.value == Mode.PublicCollection && modePublicCollectionSlug.value === collectionSlug) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
mode.value = Mode.PublicCollection;
|
|
50
|
+
modePublicCollectionSlug.value = collectionSlug;
|
|
51
|
+
|
|
52
|
+
globalSettings.updateDataVersion();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Public collections uses fixed sorting order
|
|
56
|
+
// News uses dynamic sorting order and should keep it between switching views
|
|
57
|
+
// So, if we set globalSettings.entriesOrderProperties in PublicCollection view
|
|
58
|
+
// we'll break News view sorting and confuse users
|
|
59
|
+
// => we hardcode specific order properties for PublicCollection mode
|
|
60
|
+
const activeOrderProperties = computed(() => {
|
|
61
|
+
if (mode.value === null) {
|
|
62
|
+
// Return most general order for the case when mode is not set yet
|
|
63
|
+
return e.EntriesOrderProperties.get(e.EntriesOrder.Published) as unknown as e.EntriesOrderProperty;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (mode.value == Mode.News) {
|
|
67
|
+
// use saved order mode for News view
|
|
68
|
+
return globalSettings.entriesOrderProperties as unknown as e.EntriesOrderProperty;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (mode.value == Mode.PublicCollection) {
|
|
72
|
+
// use fixed Published order for Public Collection view
|
|
73
|
+
return e.EntriesOrderProperties.get(e.EntriesOrder.Published) as unknown as e.EntriesOrderProperty;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.error(`Unknown mode ${mode.value}`);
|
|
77
|
+
|
|
78
|
+
return e.EntriesOrderProperties.get(e.EntriesOrder.Published) as unknown as e.EntriesOrderProperty;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// We bulk update entries to avoid performance degradation
|
|
82
|
+
// on triggering multiple reactivity updates for each entry
|
|
83
|
+
function registerEntries(newEntries: t.Entry[]) {
|
|
84
|
+
let delta: {[key: t.EntryId]: t.Entry} = {};
|
|
85
|
+
|
|
86
|
+
for (const entry of newEntries) {
|
|
87
|
+
if (entry.id in entries.value) {
|
|
88
|
+
if (entry.body === null && entries.value[entry.id].body !== null) {
|
|
89
|
+
entry.body = entries.value[entry.id].body;
|
|
90
|
+
}
|
|
27
91
|
}
|
|
92
|
+
delta[entry.id] = entry;
|
|
28
93
|
}
|
|
29
94
|
|
|
30
|
-
entries.value
|
|
95
|
+
entries.value = {...entries.value, ...delta};
|
|
31
96
|
}
|
|
32
97
|
|
|
33
|
-
|
|
98
|
+
async function loadEntriesAccordingToMode() {
|
|
34
99
|
const periodProperties = e.LastEntriesPeriodProperties.get(globalSettings.lastEntriesPeriod);
|
|
35
100
|
|
|
36
101
|
if (periodProperties === undefined) {
|
|
@@ -39,23 +104,74 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
39
104
|
|
|
40
105
|
const period = periodProperties.seconds;
|
|
41
106
|
|
|
107
|
+
if (mode.value === Mode.News) {
|
|
108
|
+
return await api.getLastEntries({
|
|
109
|
+
period: period
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (mode.value === Mode.PublicCollection) {
|
|
114
|
+
return await api.getLastCollectionEntries({
|
|
115
|
+
period: period,
|
|
116
|
+
collectionSlug: modePublicCollectionSlug.value
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
throw new Error(`Unknown mode ${mode.value}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const loadedEntriesReport = computedAsync(async () => {
|
|
42
124
|
// force refresh
|
|
43
125
|
globalSettings.dataVersion;
|
|
44
126
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
127
|
+
if (mode.value === null) {
|
|
128
|
+
// Do nothing until the mode is set
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const loadedEntries = await loadEntriesAccordingToMode();
|
|
48
133
|
|
|
49
134
|
const report = [];
|
|
50
135
|
|
|
136
|
+
registerEntries(loadedEntries);
|
|
137
|
+
|
|
51
138
|
for (const entry of loadedEntries) {
|
|
52
|
-
registerEntry(entry);
|
|
53
139
|
report.push(entry.id);
|
|
54
140
|
}
|
|
55
141
|
|
|
56
142
|
return report;
|
|
57
143
|
}, null);
|
|
58
144
|
|
|
145
|
+
const _sortedEntries = computed(() => {
|
|
146
|
+
if (loadedEntriesReport.value === null) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const field = activeOrderProperties.value.orderField;
|
|
151
|
+
const direction = activeOrderProperties.value.direction;
|
|
152
|
+
|
|
153
|
+
const report = utils.sortIdsList({ids: loadedEntriesReport.value, storage: entries.value, field, direction});
|
|
154
|
+
|
|
155
|
+
return report;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const visibleEntries = computed(() => {
|
|
159
|
+
let report = _sortedEntries.value.slice();
|
|
160
|
+
|
|
161
|
+
if (!globalSettings.showRead) {
|
|
162
|
+
report = report.filter((entryId) => {
|
|
163
|
+
if (displayedEntryId.value == entryId) {
|
|
164
|
+
// always show read entries with open body
|
|
165
|
+
// otherwise, they will hide right after opening it
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return !entries.value[entryId].hasMarker(e.Marker.Read);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return report;
|
|
173
|
+
});
|
|
174
|
+
|
|
59
175
|
function requestFullEntry({entryId}: {entryId: t.EntryId}) {
|
|
60
176
|
if (entryId in entries.value && entries.value[entryId].body !== null) {
|
|
61
177
|
return;
|
|
@@ -71,11 +187,9 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
71
187
|
return;
|
|
72
188
|
}
|
|
73
189
|
|
|
74
|
-
const
|
|
190
|
+
const loadedEntries = await api.getEntriesByIds({ids: ids});
|
|
75
191
|
|
|
76
|
-
|
|
77
|
-
registerEntry(entry);
|
|
78
|
-
}
|
|
192
|
+
registerEntries(loadedEntries);
|
|
79
193
|
|
|
80
194
|
requestedEntries.value = {};
|
|
81
195
|
}
|
|
@@ -96,7 +210,11 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
96
210
|
entries.value[entryId].setMarker(marker);
|
|
97
211
|
}
|
|
98
212
|
|
|
99
|
-
|
|
213
|
+
// This method may be called from public access pages, like public collections
|
|
214
|
+
// In such case user may be not logged in and we should not send API requests
|
|
215
|
+
if (globalState.isLoggedIn) {
|
|
216
|
+
await api.setMarker({entryId: entryId, marker: marker});
|
|
217
|
+
}
|
|
100
218
|
}
|
|
101
219
|
|
|
102
220
|
async function removeMarker({entryId, marker}: {entryId: t.EntryId; marker: e.Marker}) {
|
|
@@ -111,10 +229,14 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
111
229
|
entries.value[entryId].removeMarker(marker);
|
|
112
230
|
}
|
|
113
231
|
|
|
114
|
-
|
|
232
|
+
// This method may be called from public access pages, like public collections
|
|
233
|
+
// In such case user may be not logged in and we should not send API requests
|
|
234
|
+
if (globalState.isLoggedIn) {
|
|
235
|
+
await api.removeMarker({entryId: entryId, marker: marker});
|
|
236
|
+
}
|
|
115
237
|
}
|
|
116
238
|
|
|
117
|
-
async function displayEntry({entryId}: {entryId: t.EntryId}) {
|
|
239
|
+
async function displayEntry({entryId, view}: {entryId: t.EntryId; view: events.EventsViewName}) {
|
|
118
240
|
displayedEntryId.value = entryId;
|
|
119
241
|
|
|
120
242
|
requestFullEntry({entryId: entryId});
|
|
@@ -126,7 +248,7 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
126
248
|
});
|
|
127
249
|
}
|
|
128
250
|
|
|
129
|
-
await events.newsBodyOpened({entryId: entryId});
|
|
251
|
+
await events.newsBodyOpened({entryId: entryId, view: view});
|
|
130
252
|
}
|
|
131
253
|
|
|
132
254
|
function hideEntry({entryId}: {entryId: t.EntryId}) {
|
|
@@ -145,6 +267,14 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
145
267
|
removeMarker({entryId: entryId, marker: e.Marker.Read});
|
|
146
268
|
}
|
|
147
269
|
|
|
270
|
+
// TODO: Refactor for better loading tracking in the front code and in the GUI.
|
|
271
|
+
// Currently, this property is working only for the first load.
|
|
272
|
+
// => It should always be refactored to work correctly.
|
|
273
|
+
// ATTENTION: check every usage of this property while refactoring
|
|
274
|
+
const loading = computed(() => {
|
|
275
|
+
return loadedEntriesReport.value === null;
|
|
276
|
+
});
|
|
277
|
+
|
|
148
278
|
return {
|
|
149
279
|
entries,
|
|
150
280
|
requestFullEntry,
|
|
@@ -155,6 +285,11 @@ export const useEntriesStore = defineStore("entriesStore", () => {
|
|
|
155
285
|
displayEntry,
|
|
156
286
|
hideEntry,
|
|
157
287
|
undoMarkRead,
|
|
158
|
-
canUndoMarkRead
|
|
288
|
+
canUndoMarkRead,
|
|
289
|
+
setNewsMode,
|
|
290
|
+
setPublicCollectionMode,
|
|
291
|
+
loading,
|
|
292
|
+
visibleEntries,
|
|
293
|
+
activeOrderProperties
|
|
159
294
|
};
|
|
160
295
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {ref,
|
|
2
|
-
import {useRouter} from "vue-router";
|
|
1
|
+
import {ref, computed} from "vue";
|
|
3
2
|
import {defineStore} from "pinia";
|
|
4
3
|
import {computedAsync} from "@vueuse/core";
|
|
5
4
|
import {useGlobalState} from "@/stores/globalState";
|
|
@@ -8,18 +7,23 @@ import * as e from "@/logic/enums";
|
|
|
8
7
|
import * as api from "@/logic/api";
|
|
9
8
|
|
|
10
9
|
export const useGlobalSettingsStore = defineStore("globalSettings", () => {
|
|
11
|
-
const router = useRouter();
|
|
12
10
|
const globalState = useGlobalState();
|
|
13
11
|
|
|
14
12
|
// General
|
|
15
13
|
const mainPanelMode = ref(e.MainPanelMode.Entries);
|
|
16
14
|
const dataVersion = ref(0);
|
|
15
|
+
const showSidebar = ref(true);
|
|
16
|
+
const showSidebarPoint = ref(false);
|
|
17
17
|
|
|
18
18
|
// Entries
|
|
19
19
|
const lastEntriesPeriod = ref(e.LastEntriesPeriod.Day3);
|
|
20
20
|
const entriesOrder = ref(e.EntriesOrder.Score);
|
|
21
21
|
const showRead = ref(true);
|
|
22
22
|
|
|
23
|
+
const entriesOrderProperties = computed(() => {
|
|
24
|
+
return e.EntriesOrderProperties.get(entriesOrder.value);
|
|
25
|
+
});
|
|
26
|
+
|
|
23
27
|
// Feeds
|
|
24
28
|
const showFeedsDescriptions = ref(true);
|
|
25
29
|
const feedsOrder = ref(e.FeedsOrder.Title);
|
|
@@ -28,10 +32,6 @@ export const useGlobalSettingsStore = defineStore("globalSettings", () => {
|
|
|
28
32
|
// Rules
|
|
29
33
|
const rulesOrder = ref(e.RulesOrder.Tags);
|
|
30
34
|
|
|
31
|
-
watch(mainPanelMode, (newValue, oldValue) => {
|
|
32
|
-
router.push({name: mainPanelMode.value, params: {}});
|
|
33
|
-
});
|
|
34
|
-
|
|
35
35
|
function updateDataVersion() {
|
|
36
36
|
dataVersion.value++;
|
|
37
37
|
}
|
|
@@ -64,6 +64,7 @@ export const useGlobalSettingsStore = defineStore("globalSettings", () => {
|
|
|
64
64
|
lastEntriesPeriod,
|
|
65
65
|
entriesOrder,
|
|
66
66
|
showRead,
|
|
67
|
+
entriesOrderProperties,
|
|
67
68
|
dataVersion,
|
|
68
69
|
updateDataVersion,
|
|
69
70
|
showFeedsDescriptions,
|
|
@@ -71,6 +72,8 @@ export const useGlobalSettingsStore = defineStore("globalSettings", () => {
|
|
|
71
72
|
info,
|
|
72
73
|
feedsOrder,
|
|
73
74
|
failedFeedsFirst,
|
|
74
|
-
rulesOrder
|
|
75
|
+
rulesOrder,
|
|
76
|
+
showSidebar,
|
|
77
|
+
showSidebarPoint
|
|
75
78
|
};
|
|
76
79
|
});
|
package/src/views/AuthView.vue
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script lang="ts" setup>
|
|
14
|
+
import {computed, ref, onUnmounted, watch, provide, onBeforeMount} from "vue";
|
|
14
15
|
import {useRouter} from "vue-router";
|
|
15
16
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
16
17
|
import {useSupertokens} from "@/stores/supertokens";
|
|
17
18
|
import {useGlobalState} from "@/stores/globalState";
|
|
18
19
|
import {computedAsync} from "@vueuse/core";
|
|
19
|
-
import {computed, ref, onBeforeMount} from "vue";
|
|
20
20
|
import * as settings from "@/logic/settings";
|
|
21
21
|
|
|
22
22
|
const globalSettings = useGlobalSettingsStore();
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
const router = useRouter();
|
|
28
28
|
|
|
29
|
+
provide("eventsViewName", "auth");
|
|
30
|
+
|
|
29
31
|
const linkProcessed = ref(false);
|
|
30
32
|
|
|
31
33
|
function goToWorkspace() {
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
<side-panel-layout :reload-button="false">
|
|
3
3
|
<template #main-header> Collections </template>
|
|
4
4
|
|
|
5
|
-
<div
|
|
5
|
+
<div
|
|
6
|
+
v-if="collections.collectionsOrder.length > 0"
|
|
7
|
+
class="ffun-info-common">
|
|
6
8
|
<p>We've prepared thematic collections just for you.</p>
|
|
7
9
|
<p>News from collections are always tagged, ensuring you get the full power of Feeds Fun!</p>
|
|
8
10
|
</div>
|
|
9
11
|
|
|
12
|
+
<div
|
|
13
|
+
v-else
|
|
14
|
+
class="ffun-info-common">
|
|
15
|
+
<p>There are no collections.</p>
|
|
16
|
+
<p>Ask the server administrator to create some.</p>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
10
19
|
<div
|
|
11
20
|
v-for="collectionId in collections.collectionsOrder"
|
|
12
21
|
:key="collectionId"
|
|
@@ -17,7 +26,7 @@
|
|
|
17
26
|
</template>
|
|
18
27
|
|
|
19
28
|
<script lang="ts" setup>
|
|
20
|
-
import {computed, ref, onUnmounted, watch} from "vue";
|
|
29
|
+
import {computed, ref, onUnmounted, watch, provide} from "vue";
|
|
21
30
|
import {computedAsync} from "@vueuse/core";
|
|
22
31
|
import * as api from "@/logic/api";
|
|
23
32
|
import * as t from "@/logic/types";
|
|
@@ -29,6 +38,8 @@
|
|
|
29
38
|
|
|
30
39
|
const collections = useCollectionsStore();
|
|
31
40
|
|
|
41
|
+
provide("eventsViewName", "collections");
|
|
42
|
+
|
|
32
43
|
globalSettings.mainPanelMode = e.MainPanelMode.Collections;
|
|
33
44
|
</script>
|
|
34
45
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
</template>
|
|
34
34
|
|
|
35
35
|
<script lang="ts" setup>
|
|
36
|
-
import {computed, ref, onUnmounted, watch} from "vue";
|
|
36
|
+
import {computed, ref, onUnmounted, watch, provide} from "vue";
|
|
37
37
|
import {computedAsync} from "@vueuse/core";
|
|
38
38
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
39
39
|
import * as api from "@/logic/api";
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
|
|
43
43
|
const globalSettings = useGlobalSettingsStore();
|
|
44
44
|
|
|
45
|
+
provide("eventsViewName", "discovery");
|
|
46
|
+
|
|
45
47
|
globalSettings.mainPanelMode = e.MainPanelMode.Discovery;
|
|
46
48
|
</script>
|
|
47
49
|
|
package/src/views/FeedsView.vue
CHANGED
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
|
|
58
58
|
<script lang="ts" setup>
|
|
59
59
|
import _ from "lodash";
|
|
60
|
-
import {computed, ref, onUnmounted, watch} from "vue";
|
|
60
|
+
import {computed, ref, onUnmounted, watch, provide} from "vue";
|
|
61
61
|
import {computedAsync} from "@vueuse/core";
|
|
62
62
|
import {useGlobalSettingsStore} from "@/stores/globalSettings";
|
|
63
63
|
import {useFeedsStore} from "@/stores/feeds";
|
|
@@ -69,6 +69,8 @@
|
|
|
69
69
|
|
|
70
70
|
const feedsStore = useFeedsStore();
|
|
71
71
|
|
|
72
|
+
provide("eventsViewName", "feeds");
|
|
73
|
+
|
|
72
74
|
globalSettings.mainPanelMode = e.MainPanelMode.Feeds;
|
|
73
75
|
|
|
74
76
|
const sortedFeeds = computed(() => {
|
package/src/views/MainView.vue
CHANGED
|
@@ -179,7 +179,14 @@
|
|
|
179
179
|
</template>
|
|
180
180
|
|
|
181
181
|
<template #description>
|
|
182
|
-
{{ collections.collections[collectionId].description }}
|
|
182
|
+
<div>{{ collections.collections[collectionId].description }}</div>
|
|
183
|
+
<div class="mt-2">
|
|
184
|
+
<a
|
|
185
|
+
:href="publicCollectionHref(collections.collections[collectionId].slug)"
|
|
186
|
+
class="ffun-normal-link pt-4">
|
|
187
|
+
Read the news
|
|
188
|
+
</a>
|
|
189
|
+
</div>
|
|
183
190
|
</template>
|
|
184
191
|
</main-item>
|
|
185
192
|
</template>
|
|
@@ -197,8 +204,18 @@
|
|
|
197
204
|
</template>
|
|
198
205
|
|
|
199
206
|
<script lang="ts" setup>
|
|
207
|
+
import {computed, ref, onUnmounted, watch, provide} from "vue";
|
|
200
208
|
import * as settings from "@/logic/settings";
|
|
209
|
+
import {useRouter, RouterLink, RouterView} from "vue-router";
|
|
201
210
|
import {useCollectionsStore} from "@/stores/collections";
|
|
211
|
+
import * as t from "@/logic/types";
|
|
202
212
|
|
|
213
|
+
const router = useRouter();
|
|
203
214
|
const collections = useCollectionsStore();
|
|
215
|
+
|
|
216
|
+
provide("eventsViewName", "main");
|
|
217
|
+
|
|
218
|
+
function publicCollectionHref(collectionSlug: t.CollectionSlug) {
|
|
219
|
+
return router.resolve({name: "public-collection", params: {collectionSlug: collectionSlug}}).href;
|
|
220
|
+
}
|
|
204
221
|
</script>
|