Skip to content

Commit 05dd98b

Browse files
committed
Server handling improved, history works on DB, file browser optimizations in progess
1 parent 1168012 commit 05dd98b

File tree

6 files changed

+243
-113
lines changed

6 files changed

+243
-113
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ Kodi not renders properly some ASS/SSA subtitles some anime have overanimated su
1717
- Playlist handling,
1818
- Media file info,
1919
- Media collection handling,
20-
- Media status time stored on host machine. You can continue playback where you left off
20+
- Media status time can be stored on host machine. You can continue playback where you left off,
21+
- Open videos from Youtube app by using share function,
22+
- Open online streams from other apps for example [Aniyomi anime streamer](https://github.com/jmir1/aniyomi)
2123

2224
## How to use it
2325

android/app/src/main/assets/capacitor.config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"webDir": "dist",
55
"bundledWebRuntime": false,
66
"server": {
7-
"url": "http://192.168.88.4:8100"
7+
"url": "http://192.168.88.6:8100"
88
}
99
}

src/api.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from "axios";
2-
// import { toastController } from "@ionic/core";
2+
import { toastController } from "@ionic/core";
33

44
import { store } from "./store";
55

@@ -80,11 +80,9 @@ apiInstance.interceptors.response.use(
8080
);
8181

8282
export async function openToast(text, duration = 2000) {
83-
console.log(text);
84-
console.log(duration);
85-
// const toast = await toastController.create({
86-
// message: text,
87-
// duration: duration,
88-
// });
89-
// return toast.present();
83+
const toast = await toastController.create({
84+
message: text,
85+
duration: duration,
86+
});
87+
return toast.present();
9088
}

src/components/fileBrowserModal.vue

+110-54
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,57 @@
3232
</ion-toolbar>
3333
</ion-header>
3434
<ion-content
35+
ref="browserContent"
3536
class="ion-padding"
36-
v-if="(files.cwd || files.collection_id) && connectedState"
37+
v-if="(files.cwd || files.collection_id) && connectionState"
3738
>
38-
<ion-item @click="onPrevDirectoryClicked" v-if="files.prevDir">
39-
<ion-icon :icon="folder" slot="start"></ion-icon>
40-
...
41-
</ion-item>
42-
<ion-item
43-
v-for="(entry, index) in files.content"
44-
:key="index"
45-
@click="onEntryClicked(entry)"
39+
<ion-list>
40+
<ion-item @click="onPrevDirectoryClicked" v-if="files.prevDir">
41+
<ion-icon :icon="folder" slot="start"></ion-icon>
42+
...
43+
</ion-item>
44+
<ion-item
45+
v-for="(entry, index) in browsableFiles"
46+
:key="index"
47+
@click="onEntryClicked(entry)"
48+
>
49+
<ion-icon
50+
slot="start"
51+
v-if="entry.mediaStatus && entry.mediaStatus.finished === 0"
52+
class="mediaStatusProgress"
53+
:icon="decideIcon(entry)"
54+
></ion-icon>
55+
<ion-icon
56+
slot="start"
57+
v-else-if="entry.mediaStatus && entry.mediaStatus.finished === 1"
58+
class="mediaStatusFinished"
59+
:icon="decideIcon(entry)"
60+
></ion-icon>
61+
<ion-icon
62+
v-else-if="entry.type === 'subtitle'"
63+
class="fileformatSubtitle"
64+
:icon="journalOutline"
65+
slot="start"
66+
></ion-icon>
67+
<ion-icon v-else :icon="decideIcon(entry)" slot="start"></ion-icon>
68+
{{ entry.name }}
69+
</ion-item>
70+
</ion-list>
71+
72+
<ion-infinite-scroll
73+
@ionInfinite="onInfiniteScroll($event)"
74+
threshold="1000px"
75+
id="infinite-scroll"
76+
:disabled="!infiniteScrollEnabled"
4677
>
47-
<ion-icon
48-
slot="start"
49-
v-if="entry.mediaStatus && entry.mediaStatus.finished === 0"
50-
class="mediaStatusProgress"
51-
:icon="decideIcon(entry)"
52-
></ion-icon>
53-
<ion-icon
54-
slot="start"
55-
v-else-if="entry.mediaStatus && entry.mediaStatus.finished === 1"
56-
class="mediaStatusFinished"
57-
:icon="decideIcon(entry)"
58-
></ion-icon>
59-
<ion-icon
60-
v-else-if="entry.type === 'subtitle'"
61-
class="fileformatSubtitle"
62-
:icon="journalOutline"
63-
slot="start"
64-
></ion-icon>
65-
<ion-icon v-else :icon="decideIcon(entry)" slot="start"></ion-icon>
66-
{{ entry.name }}
67-
</ion-item>
78+
<ion-infinite-scroll-content
79+
loading-spinner="bubbles"
80+
loading-text="Loading more data..."
81+
>
82+
</ion-infinite-scroll-content>
83+
</ion-infinite-scroll>
6884
</ion-content>
69-
<ion-content v-else-if="!connectedState">
85+
<ion-content v-else-if="!connectionState">
7086
Lost connection to server.
7187
</ion-content>
7288
<ion-content v-else-if="!loading">
@@ -134,6 +150,8 @@ import {
134150
IonListHeader,
135151
actionSheetController,
136152
alertController,
153+
IonInfiniteScroll,
154+
IonInfiniteScrollContent,
137155
} from "@ionic/vue";
138156
import {
139157
folder,
@@ -157,21 +175,31 @@ export default {
157175
props: ["modalController", "action"],
158176
setup(props) {
159177
const store = useStore();
160-
const connectedState = computed(() => store.state.simpleapi.connected);
161178
const serverConfig = computed(
162179
() => store.state.simpleapi.MPVInfo.mpvremoteConfig
163180
);
164181
const files = ref({});
165-
const collections = ref([]);
182+
183+
// Browasble files by ion-infinite scroll
184+
const browsableFiles = ref([]);
185+
const INFINITE_SCROLL_STEP = 100;
186+
const infiniteScrollEnabled = ref(false);
187+
166188
const filesBak = ref([]);
189+
const collections = ref([]);
167190
const search = ref("");
168191
const loading = ref(true);
192+
const browserContent = ref();
193+
169194
const showOpenFolder = ref(props.action === FileBrowserActions.OPENFOLDER);
170195
const drives = ref([]);
171-
const filemanLastPath = store.state.settings.settings.filemanLastPath;
196+
197+
const filemanLastPath = store.state.settings.filemanLastPath;
172198
const sortBy = ref(FileBrowserSortBy.NAME);
173199
174-
let history = store.state.settings.settings.history || [];
200+
// let history = store.state.settings.settings.history || [];
201+
let history = store.getters["settings/getServerHistory"];
202+
175203
const titleText = computed(() => {
176204
if (files.value.dirname) return files.value.dirname;
177205
else if (files.value.collection_id) {
@@ -212,30 +240,21 @@ export default {
212240
filemanLastPath.collection_id = files.value.collection_id;
213241
}
214242
// Also save history
215-
await store.dispatch("settings/setSetting", {
216-
key: "history",
217-
value: JSON.stringify(history),
243+
await store.dispatch("settings/updateFilemanHistory", {
244+
paths: history,
245+
last_path: filemanLastPath,
218246
});
219-
220-
if (
221-
filemanLastPath.cwd != null ||
222-
filemanLastPath.collection_id != null
223-
) {
224-
return store.dispatch("settings/setSetting", {
225-
key: "filemanLastPath",
226-
value: JSON.stringify(filemanLastPath),
227-
});
228-
}
229247
};
230248
231249
const getDirectoryContents = async (path = null, collectionId = null) => {
232-
console.log("Get directory contents");
250+
console.log(
251+
`Get directory contents: path: ${path} collection:${collectionId}`
252+
);
233253
let data = {};
234254
if (path) data.path = path;
235255
if (collectionId) data.collection_id = collectionId;
236256
// Save to history
237257
// Render spinner if loading takes more than 150 msec
238-
239258
let loadingTimeout = setTimeout(() => {
240259
loading.value = true;
241260
}, 150);
@@ -245,7 +264,13 @@ export default {
245264
files.value = response.data;
246265
filesBak.value = response.data;
247266
search.value = "";
248-
267+
browsableFiles.value = files.value.content.slice(
268+
0,
269+
INFINITE_SCROLL_STEP
270+
);
271+
// Enable infinite scroll if needed.
272+
if (files.value.content.length > INFINITE_SCROLL_STEP)
273+
infiniteScrollEnabled.value = true;
249274
// Render IO related errors
250275
if (response.data.errors && response.data.errors.length > 0) {
251276
openToast(response.data.errors, 3000);
@@ -254,12 +279,32 @@ export default {
254279
.finally(() => {
255280
clearTimeout(loadingTimeout);
256281
loading.value = false;
282+
browserContent.value.$el.scrollToTop();
257283
});
258284
};
259285
286+
const onInfiniteScroll = (ev) => {
287+
// Load more items
288+
if (browsableFiles.value.length !== files.value.content.length) {
289+
console.log("Load more items");
290+
browsableFiles.value.push(
291+
...files.value.content.slice(
292+
browsableFiles.value.length,
293+
browsableFiles.value.length + INFINITE_SCROLL_STEP
294+
)
295+
);
296+
} else {
297+
infiniteScrollEnabled.value = false;
298+
console.log("Reached end");
299+
}
300+
ev.target.complete();
301+
};
302+
260303
if (filemanLastPath) {
261304
if (filemanLastPath.type == "collection") {
305+
console.log("Collection should be loaded");
262306
getDirectoryContents(null, filemanLastPath.collection_id).catch(() => {
307+
console.log("Got error, loading basic");
263308
getDirectoryContents();
264309
});
265310
} else if (filemanLastPath.type == "directory") {
@@ -300,7 +345,6 @@ export default {
300345
const { role } = await actionSheet.onDidDismiss();
301346
302347
if (role === "continue") {
303-
console.log("Continue");
304348
saveLastPath().then(() => {
305349
props.modalController.dismiss({
306350
filename: entry.fullPath,
@@ -374,7 +418,6 @@ export default {
374418
await actionSheet.present();
375419
376420
const { role } = await actionSheet.onDidDismiss();
377-
console.log(`Value:${role}`);
378421
379422
if (role !== "backdrop") {
380423
getDirectoryContents(role);
@@ -411,6 +454,11 @@ export default {
411454
files.value.content = files.value.content.filter(
412455
(el) => el.name.toLowerCase().indexOf(search.value.toLowerCase()) > -1
413456
);
457+
// Enable infinite scroll if needed.
458+
if (files.value.content.length > INFINITE_SCROLL_STEP)
459+
infiniteScrollEnabled.value = true;
460+
461+
browsableFiles.value = files.value.content.slice(0, INFINITE_SCROLL_STEP);
414462
};
415463
const onOpenDirectoryClicked = () => {
416464
saveLastPath().then(() => props.modalController.dismiss(files.value.cwd));
@@ -501,6 +549,10 @@ export default {
501549
decideIcon,
502550
onCollectionsClicked,
503551
getDirectoryContents,
552+
browsableFiles,
553+
connectionState: computed(
554+
() => store.getters["simpleapi/connectionState"]
555+
),
504556
showOpenFolder,
505557
titleText,
506558
loading,
@@ -516,10 +568,12 @@ export default {
516568
film,
517569
collections,
518570
drives,
519-
connectedState,
520571
serverConfig,
521572
funnelOutline,
522573
onSortByClicked,
574+
onInfiniteScroll,
575+
infiniteScrollEnabled,
576+
browserContent,
523577
};
524578
},
525579
components: {
@@ -537,6 +591,8 @@ export default {
537591
IonLoading,
538592
IonList,
539593
IonListHeader,
594+
IonInfiniteScroll,
595+
IonInfiniteScrollContent,
540596
},
541597
};
542598
</script>

0 commit comments

Comments
 (0)