Skip to content

Commit 8396134

Browse files
committed
fix: cloudcmd: client: all jpg files are opened with text viewer (#477)
1 parent a8d674d commit 8396134

4 files changed

Lines changed: 176 additions & 37 deletions

File tree

‎client/modules/config/input.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ export const getValue = (name, element) => {
5050
const el = getElementByName(name, element);
5151
const {type} = el;
5252

53-
if (type === 'checkbox')
53+
switch(type) {
54+
case 'checkbox':
5455
return el.checked;
5556

56-
if (type === 'number')
57+
case 'number':
5758
return Number(el.value);
5859

59-
return el.value;
60+
default:
61+
return el.value;
62+
}
6063
};
6164

6265
export const setValue = (name, value, element) => {

‎client/modules/view/index.js‎

Lines changed: 139 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
import '#css/view.css';
2+
import {rendy} from 'rendy';
23
import currify from 'currify';
34
import wraptile from 'wraptile';
5+
import {tryToCatch} from 'try-to-catch';
46
import load from 'load.js';
57
import * as _modal from '@cloudcmd/modal';
68
import _createElement from '@cloudcmd/create-element';
79
import {time} from '#common/util';
10+
import * as Files from '#dom/files';
811
import * as Events from '#dom/events';
12+
import {FS} from '#common/cloudfunc';
913
import * as Images from '#dom/images';
14+
import {encode} from '#common/entity';
15+
import {
16+
isImage,
17+
isAudio,
18+
getType,
19+
} from './types.js';
1020

1121
const CloudCmd = globalThis.CloudCmd || {};
1222
const DOM = globalThis.DOM || {};
13-
23+
const isString = (a) => typeof a === 'string';
1424
const {assign} = Object;
1525
const {isArray} = Array;
1626

@@ -40,8 +50,12 @@ CloudCmd[Name] = {
4050
const Info = DOM.CurrentInfo;
4151
const {Key} = CloudCmd;
4252

43-
let El;
53+
const basename = (a) => a
54+
.split('/')
55+
.pop();
4456

57+
let El;
58+
let TemplateAudio;
4559
let Overlay;
4660

4761
const Config = {
@@ -85,6 +99,8 @@ export async function init() {
8599
}
86100

87101
export async function show(data, options = {}) {
102+
const prefixURL = CloudCmd.prefixURL + FS;
103+
88104
if (Loading)
89105
return;
90106

@@ -110,7 +126,28 @@ export async function show(data, options = {}) {
110126

111127
Images.show.load();
112128

113-
return await viewFile();
129+
const path = prefixURL + Info.path;
130+
const type = options.raw ? '' : await getType(path);
131+
132+
switch(type) {
133+
default:
134+
return await viewFile();
135+
136+
case 'markdown':
137+
return await CloudCmd.Markdown.show(Info.path);
138+
139+
case 'html':
140+
return viewHtml(path);
141+
142+
case 'image':
143+
return viewImage(Info.path, prefixURL);
144+
145+
case 'media':
146+
return await viewMedia(path);
147+
148+
case 'pdf':
149+
return viewPDF(path);
150+
}
114151
}
115152

116153
export const _createIframe = createIframe;
@@ -140,6 +177,38 @@ function viewHtml(src, overrides = {}) {
140177
modal.open(createIframe(src), Config);
141178
}
142179

180+
function viewPDF(src) {
181+
const element = createIframe(src);
182+
183+
const options = assign({}, Config);
184+
185+
if (CloudCmd.config('showFileName'))
186+
options.title = Info.name;
187+
188+
_modal.open(element, options);
189+
}
190+
191+
async function viewMedia(path) {
192+
const [e, element] = await getMediaElement(path);
193+
194+
if (e)
195+
return alert(e);
196+
197+
const allConfig = {
198+
...Config,
199+
...{
200+
autoSize: true,
201+
afterShow: () => {
202+
element
203+
.querySelector('audio, video')
204+
.focus();
205+
},
206+
},
207+
};
208+
209+
_modal.open(element, allConfig);
210+
}
211+
143212
async function viewFile() {
144213
const [error, data] = await Info.getData();
145214

@@ -189,6 +258,73 @@ export function hide() {
189258
_modal.close();
190259
}
191260

261+
function viewImage(path, prefixURL) {
262+
const isSupportedImage = (a) => isImage(a) || a === path;
263+
const makeTitle = (path) => ({
264+
href: `${prefixURL}${path}`,
265+
title: encode(basename(path)),
266+
});
267+
268+
const names = Info.files
269+
.map(DOM.getCurrentPath)
270+
.filter(isSupportedImage);
271+
272+
const titles = names.map(makeTitle);
273+
274+
const index = names.indexOf(Info.path);
275+
276+
const imageConfig = {
277+
index,
278+
autoSize: true,
279+
arrows: true,
280+
keys: true,
281+
helpers: {
282+
title: {},
283+
},
284+
};
285+
286+
const config = {
287+
...Config,
288+
...imageConfig,
289+
};
290+
291+
_modal.open(titles, config);
292+
}
293+
294+
async function getMediaElement(src) {
295+
check(src);
296+
297+
const [error, template] = await tryToCatch(Files.get, 'view/media-tmpl');
298+
299+
if (error)
300+
return [error];
301+
302+
const {name} = Info;
303+
304+
if (!TemplateAudio)
305+
TemplateAudio = template;
306+
307+
const is = isAudio(name);
308+
const type = is ? 'audio' : 'video';
309+
310+
const innerHTML = rendy(TemplateAudio, {
311+
src,
312+
type,
313+
name,
314+
});
315+
316+
const element = _createElement('div', {
317+
innerHTML,
318+
});
319+
320+
return [null, element];
321+
}
322+
323+
function check(src) {
324+
if (!isString(src))
325+
throw Error('src should be a string!');
326+
}
327+
192328
async function loadAll() {
193329
const {DIR_DIST} = CloudCmd;
194330

‎css/main.css‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
@import './reset.css';
2-
@import './urls.css';
3-
@import './style.css';
4-
@import './icons.css';
5-
@import './help.css';
6-
@import './query.css';
7-
@import './supports.css';
1+
@import "./reset.css";
2+
@import "./urls.css";
3+
@import "./style.css";
4+
@import "./icons.css";
5+
@import "./help.css";
6+
@import "./query.css";
7+
@import "./supports.css";

‎css/urls.css‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,65 @@
55
/* http://fontello.com/ */
66
@font-face {
77
font-family: 'Fontello';
8-
src: url('../font/fontello.eot');
8+
src: url("../font/fontello.eot");
99
src:
10-
url('../font/fontello.eot?#iefix') format('embedded-opentype'),
11-
url('../font/fontello.woff2') format('woff2'),
12-
url('../font/fontello.woff') format('woff'),
13-
url('../font/fontello.ttf') format('truetype'),
14-
url('../font/fontello.svg#cloudcmd') format('svg');
10+
url("../font/fontello.eot?#iefix") format('embedded-opentype'),
11+
url("../font/fontello.woff2") format('woff2'),
12+
url("../font/fontello.woff") format('woff'),
13+
url("../font/fontello.ttf") format('truetype'),
14+
url("../font/fontello.svg#cloudcmd") format('svg');
1515
font-weight: normal;
1616
font-style: normal;
1717
}
1818

1919
@font-face {
2020
font-family: 'Droid Sans Mono';
21-
src: url('https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot');
21+
src: url("https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot");
2222
src:
2323
local('Droid Sans Mono'),
2424
local('DroidSansMono'),
25-
url('../font/DroidSansMono.eot') format('embedded-opentype'),
26-
url('https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot?#iefix')
27-
format('embedded-opentype'),
28-
url('https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot')
29-
format('embedded-opentype'),
30-
url('../font/DroidSansMono.woff2') format('woff2'),
31-
url('../font/DroidSansMono.woff') format('woff'),
32-
url('https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff')
33-
format('woff'),
25+
url("../font/DroidSansMono.eot") format('embedded-opentype'),
26+
url("https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot?#iefix")
27+
format('embedded-opentype'),
28+
url("https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJTwtzT4qNq-faudv5qbO9-U.eot")
29+
format('embedded-opentype'),
30+
url("../font/DroidSansMono.woff2") format('woff2'),
31+
url("../font/DroidSansMono.woff") format('woff'),
32+
url("https://themes.googleusercontent.com/static/fonts/droidsansmono/v5/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff")
33+
format('woff'),
3434
local('Consolas');
3535
font-style: normal;
3636
font-weight: 400;
3737
}
3838

3939
.directory {
40-
background-image: url('../img/directory.png');
40+
background-image: url("../img/directory.png");
4141
}
4242

4343
.directory-link {
44-
background-image: url('../img/directory-link.png');
44+
background-image: url("../img/directory-link.png");
4545
}
4646

4747
.file {
48-
background-image: url('../img/file.png');
48+
background-image: url("../img/file.png");
4949
}
5050

5151
.file-link {
52-
background-image: url('../img/file-link.png');
52+
background-image: url("../img/file-link.png");
5353
}
5454

5555
.archive {
56-
background-image: url('../img/archive.png');
56+
background-image: url("../img/archive.png");
5757
}
5858

5959
.archive-link {
60-
background-image: url('../img/archive-link.png');
60+
background-image: url("../img/archive-link.png");
6161
}
6262

6363
.loading-svg {
64-
background: url('../img/spinner.svg');
64+
background: url("../img/spinner.svg");
6565
}
6666

6767
.loading-gif {
68-
background: url('../img/spinner.gif');
68+
background: url("../img/spinner.gif");
6969
}

0 commit comments

Comments
 (0)