Make downloadText work on native

This commit is contained in:
Jon Staab 2026-07-08 14:53:49 -07:00
parent 47be12ff57
commit ba7a690d6f
2 changed files with 43 additions and 9 deletions

View file

@ -39,7 +39,7 @@
.replace(/NEWLINE/g, "\n\n") .replace(/NEWLINE/g, "\n\n")
.trim() .trim()
const downloadKey = () => { const downloadKey = async () => {
const sharedCopy = ` const sharedCopy = `
Most online services keep track of users by giving them a username and password. This gives the Most online services keep track of users by giving them a username and password. This gives the
service total control over their users, allowing them to ban them at any time, or sell their activity. service total control over their users, allowing them to ban them at any time, or sell their activity.
@ -52,6 +52,8 @@
account. account.
` `
let instructions: string
if (usePassword) { if (usePassword) {
if (password.length < 12) { if (password.length < 12) {
return pushToast({ return pushToast({
@ -61,7 +63,7 @@
} }
const ncryptsec = encrypt(hexToBytes(secret), password) const ncryptsec = encrypt(hexToBytes(secret), password)
const instructions = ` instructions = `
This file contains a backup of your Nostr secret key, downloaded from ${PLATFORM_NAME} and encrypted using This file contains a backup of your Nostr secret key, downloaded from ${PLATFORM_NAME} and encrypted using
a password you chose when you signed up. a password you chose when you signed up.
@ -74,11 +76,9 @@
To use it to log in to other Nostr apps, find a Nostr Signer app (https://nostrapps.com/#signers is a good To use it to log in to other Nostr apps, find a Nostr Signer app (https://nostrapps.com/#signers is a good
place to look), and import your key. place to look), and import your key.
` `
downloadText("Nostr Secret Key.txt", cleanupCopy(instructions))
} else { } else {
const nsec = nsecEncode(hexToBytes(secret)) const nsec = nsecEncode(hexToBytes(secret))
const instructions = ` instructions = `
This file contains a backup of your Nostr secret key, downloaded from ${PLATFORM_NAME}. This file contains a backup of your Nostr secret key, downloaded from ${PLATFORM_NAME}.
${sharedCopy} ${sharedCopy}
@ -90,11 +90,23 @@
To use it to log in to other Nostr apps, find a Nostr Signer app (https://nostrapps.com/#signers is a good To use it to log in to other Nostr apps, find a Nostr Signer app (https://nostrapps.com/#signers is a good
place to look), and import your key. place to look), and import your key.
` `
downloadText("Nostr Secret Key.txt", cleanupCopy(instructions))
} }
try {
await downloadText("Nostr Secret Key.txt", cleanupCopy(instructions))
didDownload = true didDownload = true
} catch (e) {
// Dismissing the native share sheet rejects with "Share canceled" — leave
// the flow gated so the user can try again rather than showing an error.
if (
!String((e as any)?.message || e)
.toLowerCase()
.includes("cancel")
) {
pushToast({theme: "error", message: "We couldn't save your key. Please try again."})
}
}
} }
const onPasswordChange = () => { const onPasswordChange = () => {

View file

@ -1,4 +1,5 @@
import {sleep, randomId} from "@welshman/lib" import {sleep, randomId} from "@welshman/lib"
import {Capacitor} from "@capacitor/core"
export {preventDefault, stopPropagation} from "svelte/legacy" export {preventDefault, stopPropagation} from "svelte/legacy"
// Anchors an @svelte-plugins/datepicker popup with fixed positioning so it // Anchors an @svelte-plugins/datepicker popup with fixed positioning so it
@ -127,7 +128,28 @@ export const createScroller = ({
export const isMobile = "ontouchstart" in document.documentElement export const isMobile = "ontouchstart" in document.documentElement
export const downloadText = (filename: string, text: string) => { export const downloadText = async (filename: string, text: string) => {
// The <a download> blob trick is a no-op in native WebViews (Android in
// particular never triggers a download), so on device we write the file and
// hand it to the native share sheet, letting the user save it to Files,
// Drive, a password manager, etc. Cache is the directory our FileProvider
// (android/app/src/main/res/xml/file_paths.xml) is configured to serve.
if (Capacitor.isNativePlatform()) {
const {Filesystem, Directory, Encoding} = await import("@capacitor/filesystem")
const {Share} = await import("@capacitor/share")
const {uri} = await Filesystem.writeFile({
path: filename,
data: text,
directory: Directory.Cache,
encoding: Encoding.UTF8,
})
await Share.share({title: filename, files: [uri]})
return
}
const blob = new Blob([text], {type: "text/plain"}) const blob = new Blob([text], {type: "text/plain"})
const url = URL.createObjectURL(blob) const url = URL.createObjectURL(blob)
const a = document.createElement("a") const a = document.createElement("a")