1
0

Handle inline images and attachments via data urls

This commit is contained in:
Zef Hemel 2023-01-08 15:29:34 +01:00
parent 0365673c41
commit 8dac58f38a
7 changed files with 53 additions and 16 deletions

View File

@ -185,6 +185,12 @@ export class Space extends EventEmitter<SpaceEvents> {
);
}
/**
* Reads an attachment
* @param name path of the attachment
* @param encoding how the return value is expected to be encoded
* @returns
*/
readAttachment(
name: string,
encoding: FileEncoding,

View File

@ -78,10 +78,10 @@ export class CapacitorSpacePrimitives implements SpacePrimitives {
}
}
return {
data,
data: data!,
meta: await this.getFileMeta(name),
};
} catch (e: any) {
} catch {
throw new Error(`Page not found`);
}
}

View File

@ -46,6 +46,11 @@ export function openUrl(url: string): Promise<void> {
return syscall("editor.openUrl", url);
}
// Force the client to download the file in dataUrl with filename as file name
export function downloadFile(filename: string, dataUrl: string): Promise<void> {
return syscall("editor.downloadFile", filename, dataUrl);
}
export function flashNotification(
message: string,
type: "info" | "error" = "info",

View File

@ -35,12 +35,24 @@ export function getAttachmentMeta(name: string): Promise<AttachmentMeta> {
return syscall("space.getAttachmentMeta", name);
}
/**
* Read an attachment from the space
* @param name path of the attachment to read
* @returns the attachment data encoded as a data URL
*/
export function readAttachment(
name: string,
): Promise<string> {
return syscall("space.readAttachment", name);
}
/**
* Writes an attachment to the space
* @param name path of the attachment to write
* @param encoding encoding of the data ("string" or "dataurl)
* @param data data itself
* @returns
*/
export function writeAttachment(
name: string,
encoding: "string" | "dataurl",
@ -49,6 +61,10 @@ export function writeAttachment(
return syscall("space.writeAttachment", name, encoding, data);
}
/**
* Deletes an attachment from the space
* @param name path of the attachment to delete
*/
export function deleteAttachment(name: string): Promise<void> {
return syscall("space.deleteAttachment", name);
}

View File

@ -1,5 +1,10 @@
import type { ClickEvent } from "$sb/app_event.ts";
import { editor, markdown, system } from "$sb/silverbullet-syscall/mod.ts";
import {
editor,
markdown,
space,
system,
} from "$sb/silverbullet-syscall/mod.ts";
import {
addParentPointers,
findNodeOfType,
@ -8,14 +13,6 @@ import {
ParseTree,
} from "$sb/lib/tree.ts";
// Checks if the URL contains a protocol, if so keeps it, otherwise assumes an attachment
function patchUrl(url: string): string {
if (url.indexOf("://") === -1) {
return `fs/${url}`;
}
return url;
}
async function actionClickOrActionEnter(
mdTree: ParseTree | null,
inNewWindow = false,
@ -71,7 +68,7 @@ async function actionClickOrActionEnter(
break;
}
case "NakedURL":
await editor.openUrl(patchUrl(mdTree.children![0].text!));
await editor.openUrl(mdTree.children![0].text!);
break;
case "Image":
case "Link": {
@ -79,11 +76,18 @@ async function actionClickOrActionEnter(
if (!urlNode) {
return;
}
const url = patchUrl(urlNode.children![0].text!);
let url = urlNode.children![0].text!;
if (url.length <= 1) {
return editor.flashNotification("Empty link, ignoring", "error");
}
await editor.openUrl(url);
if (url.indexOf("://") === -1) {
url = decodeURIComponent(url);
// attachment URL, let's fetch as a data url
const dataUrl = await space.readAttachment(url);
return editor.downloadFile(url, dataUrl);
} else {
await editor.openUrl(url);
}
break;
}
case "CommandLink": {

View File

@ -27,8 +27,8 @@ class InlineImageWidget extends WidgetType {
if (this.url.startsWith("http")) {
img.src = this.url;
} else {
// Specific to mobile
this.space.readAttachment(decodeURI(this.url), "dataurl").then(
// Load the image as a dataURL and inject it into the img's src attribute
this.space.readAttachment(decodeURIComponent(this.url), "dataurl").then(
({ data }) => {
img.src = data as string;
},

View File

@ -38,6 +38,12 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
win.focus();
}
},
"editor.downloadFile": (_ctx, filename: string, dataUrl: string) => {
const link = document.createElement("a");
link.href = dataUrl;
link.download = filename;
link.click();
},
"editor.flashNotification": (
_ctx,
message: string,