feeds-fun 1.22.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feeds-fun",
3
- "version": "1.22.0",
3
+ "version": "1.22.1",
4
4
  "author": "Aliaksei Yaletski (Tiendil) <a.eletsky@gmail.com> (https://tiendil.org/)",
5
5
  "description": "Frontend for the Feeds Fun — web-based news reader",
6
6
  "keywords": [
@@ -38,6 +38,7 @@
38
38
  "axios": "^1.7.7",
39
39
  "dompurify": "^3.1.7",
40
40
  "lodash": "^4.17.21",
41
+ "neverthrow": "^8.2.0",
41
42
  "pinia": "^2.2.6",
42
43
  "set-interval-async": "^3.0.3",
43
44
  "vanilla-cookieconsent": "^3.1.0",
@@ -49,7 +50,7 @@
49
50
  "@tailwindcss/typography": "^0.5.15",
50
51
  "@types/dompurify": "^3.0.5",
51
52
  "@types/jsdom": "^21.1.7",
52
- "@types/lodash": "^4.17.13",
53
+ "@types/lodash": "^4.17.21",
53
54
  "@types/node": "^22.9.0",
54
55
  "@vitejs/plugin-vue": "^5.1.4",
55
56
  "@vue/eslint-config-prettier": "^10.1.0",
@@ -58,6 +59,7 @@
58
59
  "@vue/tsconfig": "^0.5.1",
59
60
  "autoprefixer": "^10.4.20",
60
61
  "eslint": "^9.14.0",
62
+ "eslint-plugin-neverthrow": "^1.1.4",
61
63
  "eslint-plugin-vue": "^9.30.0",
62
64
  "jsdom": "^25.0.1",
63
65
  "npm-run-all": "^4.1.5",
@@ -30,9 +30,9 @@
30
30
 
31
31
  <p
32
32
  v-if="error"
33
- class="ffun-info-bad mt-4"
34
- >Error occurred! Maybe you chose a wrong file?</p
35
- >
33
+ class="ffun-info-bad mt-4">
34
+ {{ errorMessage }}
35
+ </p>
36
36
  </div>
37
37
  </template>
38
38
 
@@ -52,6 +52,7 @@
52
52
  const loading = ref(false);
53
53
  const loaded = ref(false);
54
54
  const error = ref(false);
55
+ const errorMessage = ref("");
55
56
 
56
57
  function uploadFile(event: Event) {
57
58
  opmlFile.value = (event.target as HTMLInputElement).files?.[0] ?? null;
@@ -77,20 +78,30 @@
77
78
  });
78
79
 
79
80
  try {
80
- await api.addOPML({content: content});
81
-
82
- // loading an OPML file is pretty rare and significantly changes the list of feeds
83
- // => we can force data to be reloaded
84
- globalSettings.updateDataVersion();
81
+ let result = await api.addOPML({content: content});
82
+
83
+ result.match(
84
+ // loading an OPML file is pretty rare and significantly changes the list of feeds
85
+ // => we can force data to be reloaded
86
+ (data) => {
87
+ globalSettings.updateDataVersion();
88
+ error.value = false;
89
+ loaded.value = true;
90
+ },
91
+ (err) => {
92
+ error.value = true;
93
+ errorMessage.value = err.message;
94
+ loaded.value = false;
95
+ }
96
+ );
85
97
 
86
98
  loading.value = false;
87
- loaded.value = true;
88
- error.value = false;
89
99
  } catch (e) {
90
100
  console.error(e);
91
101
  loading.value = false;
92
102
  loaded.value = false;
93
103
  error.value = true;
104
+ errorMessage.value = "Error occurred! Maybe you chose a wrong file?";
94
105
  }
95
106
  }
96
107
  </script>
@@ -169,10 +169,10 @@
169
169
  const tagInfo = tagsStore.tags[tag];
170
170
 
171
171
  if (tagInfo === undefined || tagInfo.name === null) {
172
- return tag.includes(tagNameFilter.value);
172
+ return tag.includes(textFilter);
173
173
  }
174
174
 
175
- return tagInfo.name.includes(tagNameFilter.value);
175
+ return tagInfo.name.includes(textFilter);
176
176
  });
177
177
 
178
178
  return values;
package/src/logic/api.ts CHANGED
@@ -5,6 +5,7 @@ import type * as e from "@/logic/enums";
5
5
  import * as settings from "@/logic/settings";
6
6
  import * as cookieConsent from "@/plugins/CookieConsent";
7
7
  import {useGlobalState} from "@/stores/globalState";
8
+ import {ok, err, Result} from "neverthrow";
8
9
 
9
10
  ///////////////
10
11
  // API handlers
@@ -13,6 +14,8 @@ import {useGlobalState} from "@/stores/globalState";
13
14
  const publicEntryPoint = "/spa/api/public";
14
15
  const privateEntryPoint = "/spa/api/private";
15
16
 
17
+ export const downloadOPMLUrl = `${privateEntryPoint}/get-opml`;
18
+
16
19
  const apiPublic = axios.create({baseURL: publicEntryPoint, withCredentials: true});
17
20
  const apiPrivate = axios.create({baseURL: privateEntryPoint, withCredentials: true});
18
21
 
@@ -101,11 +104,22 @@ async function postPublic({url, data}: {url: string; data: any}) {
101
104
  return response.data;
102
105
  }
103
106
 
107
+ // TODO: deprecated, use postPrivateResult instead
104
108
  async function postPrivate({url, data, config}: {url: string; data: any; config?: any}) {
105
109
  const response = await apiPrivate.post(url, data, config);
106
110
  return response.data;
107
111
  }
108
112
 
113
+ async function postPrivateResult({url, data, config}: {url: string; data: any; config?: any}) {
114
+ const response = await apiPrivate.post(url, data, config);
115
+
116
+ if (response.data.status === "error") {
117
+ return err(new t.ApiError(response.data.code, response.data.message));
118
+ }
119
+
120
+ return ok(response.data.data);
121
+ }
122
+
109
123
  /////////////
110
124
  // Public API
111
125
  /////////////
@@ -410,7 +424,7 @@ export async function addFeed({url}: {url: string}) {
410
424
  }
411
425
 
412
426
  export async function addOPML({content}: {content: string}) {
413
- await postPrivate({url: "/add-opml", data: {content: content}});
427
+ return await postPrivateResult({url: "/add-opml", data: {content: content}});
414
428
  }
415
429
 
416
430
  export async function unsubscribe({feedId}: {feedId: t.FeedId}) {
@@ -557,3 +557,13 @@ export class userInfo {
557
557
  export function userInfoFromJSON({userId}: {userId: string}): userInfo {
558
558
  return new userInfo({userId});
559
559
  }
560
+
561
+ export class ApiError {
562
+ readonly code: string;
563
+ readonly message: string;
564
+
565
+ constructor(code: string, message: string) {
566
+ this.code = code;
567
+ this.message = message;
568
+ }
569
+ }
@@ -28,7 +28,7 @@
28
28
  <template #side-menu-item-4>
29
29
  <a
30
30
  class="ffun-form-button p-1 my-1 block w-full text-center"
31
- href="/api/get-opml"
31
+ :href="api.downloadOPMLUrl"
32
32
  target="_blank"
33
33
  title="Download OPML file with all your feeds"
34
34
  >Download OPML</a