@axium/storage 0.16.4 → 0.16.5
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/lib/List.svelte +75 -58
- package/package.json +1 -1
package/lib/List.svelte
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { AccessControllable, UserPublic } from '@axium/core';
|
|
5
5
|
import { formatBytes } from '@axium/core/format';
|
|
6
6
|
import { forMime as iconForMime } from '@axium/core/icons';
|
|
7
|
+
import { errorText } from '@axium/core/io';
|
|
7
8
|
import { downloadItem, getDirectoryMetadata, updateItemMetadata } from '@axium/storage/client';
|
|
8
9
|
import { openers, previews } from '@axium/storage/client/3rd-party';
|
|
9
10
|
import type { StorageItemMetadata } from '@axium/storage/common';
|
|
@@ -48,12 +49,12 @@
|
|
|
48
49
|
<span>Size</span>
|
|
49
50
|
</div>
|
|
50
51
|
{#each items as item, i (item.id)}
|
|
51
|
-
{@const itemOpeners = openers.filter(opener => opener.types.includes(item.type))}
|
|
52
52
|
<div
|
|
53
53
|
class="list-item"
|
|
54
54
|
onclick={async () => {
|
|
55
55
|
if (item.type != 'inode/directory') {
|
|
56
|
-
|
|
56
|
+
activeIndex = i;
|
|
57
|
+
dialogs.preview.showModal();
|
|
57
58
|
} else if (appMode) location.href = '/files/' + item.id;
|
|
58
59
|
else items = await getDirectoryMetadata(item.id);
|
|
59
60
|
}}
|
|
@@ -85,62 +86,6 @@
|
|
|
85
86
|
/>
|
|
86
87
|
{@render action('download', 'download', i)}
|
|
87
88
|
{@render action('trash', 'trash', i)}
|
|
88
|
-
<dialog bind:this={dialogs['preview:' + item.id]} class="preview">
|
|
89
|
-
<div class="preview-top-bar">
|
|
90
|
-
<div class="title">{item.name}</div>
|
|
91
|
-
{#if itemOpeners.length}
|
|
92
|
-
{@const [first, ...others] = itemOpeners}
|
|
93
|
-
<div class="openers">
|
|
94
|
-
<span>Open with <a href={first.openURL(item)} target="_blank">{first.name}</a></span>
|
|
95
|
-
{#if others.length}
|
|
96
|
-
<Popover>
|
|
97
|
-
{#snippet toggle()}
|
|
98
|
-
<span class="popover-toggle"><Icon i="caret-down" /></span>
|
|
99
|
-
{/snippet}
|
|
100
|
-
{#each others as opener}
|
|
101
|
-
<a href={opener.openURL(item)} target="_blank">{opener.name}</a>
|
|
102
|
-
{/each}
|
|
103
|
-
</Popover>
|
|
104
|
-
{/if}
|
|
105
|
-
</div>
|
|
106
|
-
{/if}
|
|
107
|
-
<div class="actions">
|
|
108
|
-
{@render action('rename', 'pencil', i, true)}
|
|
109
|
-
{@render action('share:' + item.id, 'user-group', i, true)}
|
|
110
|
-
{@render action('download', 'download', i, true)}
|
|
111
|
-
{@render action('trash', 'trash', i, true)}
|
|
112
|
-
<span class="mobile-hide" onclick={() => dialogs['preview:' + item.id].close()}>
|
|
113
|
-
<Icon i="xmark" --size="20px" />
|
|
114
|
-
</span>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
<div class="content">
|
|
118
|
-
{#if item.type.startsWith('image/')}
|
|
119
|
-
<img src={item.dataURL} alt={item.name} width="100%" />
|
|
120
|
-
{:else if item.type.startsWith('audio/')}
|
|
121
|
-
<audio src={item.dataURL} controls></audio>
|
|
122
|
-
{:else if item.type.startsWith('video/')}
|
|
123
|
-
<video src={item.dataURL} controls width="100%">
|
|
124
|
-
<track kind="captions" />
|
|
125
|
-
</video>
|
|
126
|
-
{:else if item.type == 'application/pdf'}
|
|
127
|
-
<object data={item.dataURL} type="application/pdf" width="100%" height="100%">
|
|
128
|
-
<embed src={item.dataURL} type="application/pdf" width="100%" height="100%" />
|
|
129
|
-
<p>PDF not displayed? <a href={item.dataURL} download={item.name}>Download</a></p>
|
|
130
|
-
</object>
|
|
131
|
-
{:else if item.type.startsWith('text/')}
|
|
132
|
-
<pre
|
|
133
|
-
class="full-fill preview-text">{#await downloadItem(item.id).then( b => b.text() ) then content}{content}{/await}</pre>
|
|
134
|
-
{:else if previews.has(item.type)}
|
|
135
|
-
{@render previews.get(item.type)!(item)}
|
|
136
|
-
{:else}
|
|
137
|
-
<div class="full-fill no-preview">
|
|
138
|
-
<Icon i="eye-slash" --size="50px" />
|
|
139
|
-
<span>Preview not available</span>
|
|
140
|
-
</div>
|
|
141
|
-
{/if}
|
|
142
|
-
</div>
|
|
143
|
-
</dialog>
|
|
144
89
|
</div>
|
|
145
90
|
</div>
|
|
146
91
|
{:else}
|
|
@@ -148,6 +93,78 @@
|
|
|
148
93
|
{/each}
|
|
149
94
|
</div>
|
|
150
95
|
|
|
96
|
+
<dialog bind:this={dialogs.preview} class="preview">
|
|
97
|
+
{#if activeItem}
|
|
98
|
+
{@const { type, dataURL } = activeItem}
|
|
99
|
+
{@const itemOpeners = openers.filter(opener => opener.types.includes(type))}
|
|
100
|
+
<div class="preview-top-bar">
|
|
101
|
+
<div class="title">{activeItem.name}</div>
|
|
102
|
+
{#if itemOpeners.length}
|
|
103
|
+
{@const [first, ...others] = itemOpeners}
|
|
104
|
+
<div class="openers">
|
|
105
|
+
<span>Open with <a href={first.openURL(activeItem)} target="_blank">{first.name}</a></span>
|
|
106
|
+
{#if others.length}
|
|
107
|
+
<Popover>
|
|
108
|
+
{#snippet toggle()}
|
|
109
|
+
<span class="popover-toggle"><Icon i="caret-down" /></span>
|
|
110
|
+
{/snippet}
|
|
111
|
+
{#each others as opener}
|
|
112
|
+
<a href={opener.openURL(activeItem)} target="_blank">{opener.name}</a>
|
|
113
|
+
{/each}
|
|
114
|
+
</Popover>
|
|
115
|
+
{/if}
|
|
116
|
+
</div>
|
|
117
|
+
{/if}
|
|
118
|
+
<div class="actions">
|
|
119
|
+
{@render action('rename', 'pencil', i, true)}
|
|
120
|
+
{@render action('share:' + activeItem.id, 'user-group', i, true)}
|
|
121
|
+
{@render action('download', 'download', i, true)}
|
|
122
|
+
{@render action('trash', 'trash', i, true)}
|
|
123
|
+
<span class="mobile-hide" onclick={() => dialogs.preview.close()}>
|
|
124
|
+
<Icon i="xmark" --size="20px" />
|
|
125
|
+
</span>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="content">
|
|
129
|
+
{#if type.startsWith('image/')}
|
|
130
|
+
<img src={dataURL} alt={activeItem.name} width="100%" />
|
|
131
|
+
{:else if type.startsWith('audio/')}
|
|
132
|
+
<audio src={dataURL} controls></audio>
|
|
133
|
+
{:else if type.startsWith('video/')}
|
|
134
|
+
<video src={dataURL} controls width="100%">
|
|
135
|
+
<track kind="captions" />
|
|
136
|
+
</video>
|
|
137
|
+
{:else if type == 'application/pdf'}
|
|
138
|
+
<object data={dataURL} type="application/pdf" width="100%" height="100%">
|
|
139
|
+
<embed src={dataURL} type="application/pdf" width="100%" height="100%" />
|
|
140
|
+
<p>PDF not displayed? <a href={dataURL} download={activeItem.name}>Download</a></p>
|
|
141
|
+
</object>
|
|
142
|
+
{:else if type.startsWith('text/')}
|
|
143
|
+
{#await downloadItem(activeItem.id).then(b => b.text())}
|
|
144
|
+
<div class="full-fill no-preview">
|
|
145
|
+
<Icon i="cloud-arrow-down" --size="50px" />
|
|
146
|
+
<span>Loading</span>
|
|
147
|
+
</div>
|
|
148
|
+
{:then content}
|
|
149
|
+
<pre class="full-fill preview-text">{content}</pre>
|
|
150
|
+
{:catch}
|
|
151
|
+
<div class="full-fill no-preview">
|
|
152
|
+
<Icon i="cloud-exclamation" --size="50px" />
|
|
153
|
+
<span>Error loading preview. You might not have permission to view this file.</span>
|
|
154
|
+
</div>
|
|
155
|
+
{/await}
|
|
156
|
+
{:else if previews.has(type)}
|
|
157
|
+
{@render previews.get(type)!(activeItem)}
|
|
158
|
+
{:else}
|
|
159
|
+
<div class="full-fill no-preview">
|
|
160
|
+
<Icon i="eye-slash" --size="50px" />
|
|
161
|
+
<span>Preview not available</span>
|
|
162
|
+
</div>
|
|
163
|
+
{/if}
|
|
164
|
+
</div>
|
|
165
|
+
{/if}
|
|
166
|
+
</dialog>
|
|
167
|
+
|
|
151
168
|
<FormDialog
|
|
152
169
|
bind:dialog={dialogs.rename}
|
|
153
170
|
submitText="Rename"
|