diff --git a/ionic-gib/package-lock.json b/ionic-gib/package-lock.json index 0ea344c8..18385650 100644 --- a/ionic-gib/package-lock.json +++ b/ionic-gib/package-lock.json @@ -1,12 +1,12 @@ { "name": "ionicgib", - "version": "0.1.1", + "version": "0.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ionicgib", - "version": "0.1.1", + "version": "0.1.3", "dependencies": { "@angular-devkit/schematics": "^13.1.2", "@angular/common": "~13.1.1", diff --git a/ionic-gib/package.json b/ionic-gib/package.json index b4b82b08..709ad283 100644 --- a/ionic-gib/package.json +++ b/ionic-gib/package.json @@ -1,6 +1,6 @@ { "name": "ionicgib", - "version": "0.1.1", + "version": "0.1.3", "author": "William Raiford", "repository": { "url": "https://github.com/wraiford/ibgib", @@ -47,6 +47,7 @@ "ff:1": "web-ext run -s './www' -t firefox-desktop --firefox-profile=ibgibtest1 --keep-profile-changes --browser-console", "ff:2": "web-ext run -s './www' -t firefox-desktop --firefox-profile=ibgibtest2 --keep-profile-changes --browser-console", "ff:3": "web-ext run -s './www' -t firefox-desktop --firefox-profile=ibgibtest3 --keep-profile-changes --browser-console", + "ff:mobile:android": "web-ext run -s './www' -t firefox-android", "chrome": "web-ext run -s './www' -t chromium --keep-profile-changes --browser-console", "test": "ng test", "lint": "ng lint", diff --git a/ionic-gib/src/app/app.component.ts b/ionic-gib/src/app/app.component.ts index 1385e885..c9d16a24 100644 --- a/ionic-gib/src/app/app.component.ts +++ b/ionic-gib/src/app/app.component.ts @@ -148,7 +148,6 @@ export class AppComponent extends IbgibComponentBase menuOpen: string = 'tags'; constructor( - private platform: Platform, private splashScreen: SplashScreen, private statusBar: StatusBar, protected common: CommonService, @@ -173,7 +172,7 @@ export class AppComponent extends IbgibComponentBase if (logalot) { console.log(`${lc} starting...`); } this.initializing = true; - this.platform.ready().then(async () => { + this.common.platform.ready().then(async () => { this.statusBar.styleDefault(); let navToAddr: IbGibAddr; @@ -230,7 +229,7 @@ export class AppComponent extends IbgibComponentBase } // navToAddr = this.tagsAddr; - this.platform.backButton.subscribeWithPriority(10, async () => { + this.common.platform.backButton.subscribeWithPriority(10, async () => { if (this.common?.nav) { await this.common.nav.back(); } }); diff --git a/ionic-gib/src/app/common/action-bar/action-bar.component.html b/ionic-gib/src/app/common/action-bar/action-bar.component.html index b4bef5fb..bc026911 100644 --- a/ionic-gib/src/app/common/action-bar/action-bar.component.html +++ b/ionic-gib/src/app/common/action-bar/action-bar.component.html @@ -1,7 +1,7 @@
- + @@ -9,7 +9,7 @@ @@ -17,7 +17,7 @@ diff --git a/ionic-gib/src/app/common/action-bar/action-bar.component.scss b/ionic-gib/src/app/common/action-bar/action-bar.component.scss index 44b68d5c..b50bf678 100644 --- a/ionic-gib/src/app/common/action-bar/action-bar.component.scss +++ b/ionic-gib/src/app/common/action-bar/action-bar.component.scss @@ -14,3 +14,7 @@ input { ion-icon { margin: 0px; } + +ion-button { + border-radius: 5px; +} \ No newline at end of file diff --git a/ionic-gib/src/app/common/action-bar/action-bar.component.ts b/ionic-gib/src/app/common/action-bar/action-bar.component.ts index b1ed77cb..6b19a833 100644 --- a/ionic-gib/src/app/common/action-bar/action-bar.component.ts +++ b/ionic-gib/src/app/common/action-bar/action-bar.component.ts @@ -1,9 +1,11 @@ import { Component, OnInit, ChangeDetectorRef, Input } from '@angular/core'; -import { Plugins, Camera, CameraResultType, ActionSheetOptionStyle } from '@capacitor/core'; +import { + Plugins, Camera, CameraResultType, Filesystem, +} from '@capacitor/core'; const { Modals } = Plugins; import { IbGibAddr, IbGibRel8ns, V1 } from 'ts-gib'; -import { hash, getIbGibAddr, getTimestamp, getIbAndGib, pretty } from 'ts-gib/dist/helper'; +import { hash, getIbGibAddr, getTimestamp, pretty } from 'ts-gib/dist/helper'; import { Factory_V1 as factory, IbGibRel8ns_V1, IbGib_V1 } from 'ts-gib/dist/V1'; import * as h from 'ts-gib/dist/helper'; @@ -11,7 +13,6 @@ import { CommonService } from 'src/app/services/common.service'; import { ActionItem, PicData, CommentData, SyncSpaceResultIbGib, ActionItemName, } from '../types'; -import { ChooseIconModalComponent, IconItem } from '../choose-icon-modal/choose-icon-modal.component'; import { IbGibSpaceAny } from '../witnesses/spaces/space-base-v1'; import { IbgibComponentBase } from '../bases/ibgib-component-base'; import { @@ -22,6 +23,7 @@ import { import * as c from '../constants'; import { getGib } from 'ts-gib/dist/V1/transforms/transform-helper'; + const logalot = c.GLOBAL_LOG_A_LOT || false; const debugBorder = c.GLOBAL_DEBUG_BORDER || false; @@ -62,7 +64,6 @@ export class ActionBarComponent extends IbgibComponentBase type: 'inputfile-camera', text: 'camera', icons: ['camera-outline'], - // filepicked: async (event) => await this.actionAddImage(event), filepicked: async (event) => await this.handleHtml5PicButton(event), }, { @@ -225,13 +226,13 @@ export class ActionBarComponent extends IbgibComponentBase const binIb = getBinIb({binHash, binExt: ext}); const binIbGib: IbGib_V1 = { ib: binIb, data: imageBase64 }; + const binGib = await getGib({ibGib: binIbGib, hasTjp: false}); binIbGib.gib = binGib; const binAddr = h.getIbGibAddr({ibGib: binIbGib}); if (logalot) { console.log(`${lc} saving initial ibgib pic with data = imageBase64...`); } const resSaveBin = await this.common.ibgibs.put({ibGib: binIbGib}); - // await this.ibgibs.put({binData: image.base64String, binExt: ext}); if (!resSaveBin.success) { throw new Error(resSaveBin.errorMsg || 'error saving pic'); } if (logalot) { console.log(`${lc} saving initial ibgib pic with data = imageBase64 complete.`); } @@ -408,17 +409,27 @@ export class ActionBarComponent extends IbgibComponentBase } reader.onload = async (_: any) => { - let imageBase64 = reader.result.toString().split('base64,')[1]; - let binHash = await hash({s: imageBase64}); - const filenameWithExt = file.name; - const filenamePieces = filenameWithExt.split('.'); - const filename = filenamePieces.slice(0, filenamePieces.length-1).join('.'); - const ext = filenamePieces.slice(filenamePieces.length-1)[0]; - - await this.doPic({imageBase64, binHash, filename, ext}); - if (actionItem) { - actionItem.busy = false; - this.ref.detectChanges(); + const lc2 = `${lc}[reader.onload]`; + try { + if (logalot) { console.log(`${lc2} starting... (I: 1e948476ca86b328a12700dc57be0a22)`); } + let imageBase64 = reader.result.toString().split('base64,')[1]; + let binHash = await hash({s: imageBase64}); + const filenameWithExt = file.name; + const filenamePieces = filenameWithExt.split('.'); + const filename = filenamePieces.slice(0, filenamePieces.length-1).join('.'); + const ext = filenamePieces.slice(filenamePieces.length-1)[0]; + + await this.doPic({imageBase64, binHash, filename, ext}); + + } catch (error) { + console.error(`${lc2} ${error.message}`); + throw error; + } finally { + if (actionItem) { + actionItem.busy = false; + this.ref.detectChanges(); + } + if (logalot) { console.log(`${lc2} complete. (I: d88dcaeb874c4f049d51d58655dc2b62)`); } } }; reader.readAsDataURL(file); diff --git a/ionic-gib/src/app/common/bases/create-modal-component-base.ts b/ionic-gib/src/app/common/bases/create-modal-component-base.ts index 0ed7c496..80153915 100644 --- a/ionic-gib/src/app/common/bases/create-modal-component-base.ts +++ b/ionic-gib/src/app/common/bases/create-modal-component-base.ts @@ -10,7 +10,8 @@ import { } from '../types'; import { getRegExp } from '../helper'; -const logalot = c.GLOBAL_LOG_A_LOT || false || true; +const logalot = c.GLOBAL_LOG_A_LOT || false; + /** * Prompts the user for information gathering and generates a new ibGib. diff --git a/ionic-gib/src/app/common/bases/ibgib-component-base.ts b/ionic-gib/src/app/common/bases/ibgib-component-base.ts index 6c56971b..a36be4f1 100644 --- a/ionic-gib/src/app/common/bases/ibgib-component-base.ts +++ b/ionic-gib/src/app/common/bases/ibgib-component-base.ts @@ -11,6 +11,7 @@ import { IbGibAddr, Ib, Gib, } from "ts-gib"; import * as c from '../../common/constants'; import { IbgibItem, PicData, CommentData, LatestEventInfo } from '../types'; import { CommonService, NavInfo } from 'src/app/services/common.service'; +import { Capacitor } from '@capacitor/core'; const logalot = c.GLOBAL_LOG_A_LOT || false; const debugBorder = c.GLOBAL_DEBUG_BORDER || false; @@ -159,12 +160,23 @@ export abstract class IbgibComponentBase */ protected subLatest: Subscription; + @Input() + platform: string = Capacitor.getPlatform(); + + @Input() + get ios(): boolean { return this.platform === 'ios'; } + @Input() + get android(): boolean { return this.platform === 'android'; } + @Input() + get web(): boolean { return this.platform === 'web'; } + constructor( protected common: CommonService, protected ref: ChangeDetectorRef, ) { const lc = `${this.lc}[ctor]`; if (logalot) { console.log(`${lc}${c.GLOBAL_TIMER_NAME}`); console.timeLog(c.GLOBAL_TIMER_NAME); } + } /** @@ -403,6 +415,8 @@ export abstract class IbgibComponentBase item.timestamp = data.timestamp; if (logalot) { console.log(`${lc} initial item.picSrc.length: ${item?.picSrc?.length}`); } + item.filenameWithExt = `${data.filename || data.binHash}.${data.ext}`; + const delayRefDetectChangesMs = 2000; // hack if (resGet.success && resGet.ibGibs?.length === 1 && resGet.ibGibs[0]!.data) { item.picSrc = `data:image/jpeg;base64,${resGet.ibGibs![0].data!}`; diff --git a/ionic-gib/src/app/common/bases/ibgib-list-component-base.ts b/ionic-gib/src/app/common/bases/ibgib-list-component-base.ts index b2b2649e..8e801742 100644 --- a/ionic-gib/src/app/common/bases/ibgib-list-component-base.ts +++ b/ionic-gib/src/app/common/bases/ibgib-list-component-base.ts @@ -8,7 +8,7 @@ import * as c from '../constants'; import { IbGib_V1 } from 'ts-gib/dist/V1'; import { unique } from '../helper/utils'; -const logalot = c.GLOBAL_LOG_A_LOT || false || true; +const logalot = c.GLOBAL_LOG_A_LOT || false; @Injectable({providedIn: "root"}) export abstract class IbgibListComponentBase diff --git a/ionic-gib/src/app/common/constants.ts b/ionic-gib/src/app/common/constants.ts index 4d2d2375..96258fbd 100644 --- a/ionic-gib/src/app/common/constants.ts +++ b/ionic-gib/src/app/common/constants.ts @@ -85,6 +85,7 @@ export const IBGIB_IBGIBS_SUBPATH = 'ibgibs'; * e.g. settings, a separate folder will be useful. */ export const IBGIB_META_SUBPATH = 'meta'; +export const IBGIB_DOWNLOADED_PICS_SUBPATH = 'DownloadedPics'; export const VALID_SPACE_NAME_EXAMPLES = [ 'justLetters', 'valid_here', 'hyphens-allowed', '0CanStartOrEndWithNumbers9' diff --git a/ionic-gib/src/app/common/types/ux.ts b/ionic-gib/src/app/common/types/ux.ts index c509ac44..843d636a 100644 --- a/ionic-gib/src/app/common/types/ux.ts +++ b/ionic-gib/src/app/common/types/ux.ts @@ -81,6 +81,10 @@ export interface IbgibItem { * ``` */ picSrc?: any; + /** + * If it's a pic/binary, then this is the filename.ext + */ + filenameWithExt?: string; // picSrc?: string; text?: string; isMeta?: boolean; diff --git a/ionic-gib/src/app/common/witnesses/spaces/ionic-space-v1.ts b/ionic-gib/src/app/common/witnesses/spaces/ionic-space-v1.ts index 3750b620..991dd3c3 100644 --- a/ionic-gib/src/app/common/witnesses/spaces/ionic-space-v1.ts +++ b/ionic-gib/src/app/common/witnesses/spaces/ionic-space-v1.ts @@ -838,6 +838,7 @@ export class IonicSpace_V1< // if (logalot) { console.log(`${lc} tried to delete file first for android, but failed`); } // } // } + if (logalot) { console.log(`${lc} path: ${path}, directory: ${thisData.baseDir}, encoding: ${thisData.encoding} (I: d4440ececbe6c859f8fcf6d7ece12522)`); } const resWrite = await Filesystem.writeFile({ path, data, diff --git a/ionic-gib/src/app/ibgib/ibgib.page.html b/ionic-gib/src/app/ibgib/ibgib.page.html index 152d9ed8..329c8dc8 100644 --- a/ionic-gib/src/app/ibgib/ibgib.page.html +++ b/ionic-gib/src/app/ibgib/ibgib.page.html @@ -31,12 +31,31 @@ - + + + + + + + + + + + + + @@ -145,5 +164,8 @@ - + + diff --git a/ionic-gib/src/app/ibgib/ibgib.page.scss b/ionic-gib/src/app/ibgib/ibgib.page.scss index 32eef794..1c1d415d 100644 --- a/ionic-gib/src/app/ibgib/ibgib.page.scss +++ b/ionic-gib/src/app/ibgib/ibgib.page.scss @@ -54,7 +54,7 @@ pre { action-bar, ion-footer { display: flex; flex-direction: row; - height: 55px !important; + // height: 55px !important; } .toolbar-title-btn { diff --git a/ionic-gib/src/app/ibgib/ibgib.page.ts b/ionic-gib/src/app/ibgib/ibgib.page.ts index 0ec69229..7dc20579 100644 --- a/ionic-gib/src/app/ibgib/ibgib.page.ts +++ b/ionic-gib/src/app/ibgib/ibgib.page.ts @@ -17,7 +17,7 @@ import { CommonService } from '../services/common.service'; import { SPECIAL_URLS } from '../common/constants'; import { LatestEventInfo, PicData, } from '../common/types'; import { IbgibFullscreenModalComponent } from '../common/ibgib-fullscreen-modal/ibgib-fullscreen-modal.component'; -import { getFnAlert, getFnPrompt, pathExists, } from '../common/helper'; +import { ensureDirPath, getBlob, getFnAlert, getFnConfirm, getFnPrompt, pathExists, writeFile, } from '../common/helper'; import { concatMap } from 'rxjs/operators'; import { ChooseIconModalComponent, IconItem } from '../common/choose-icon-modal/choose-icon-modal.component'; import { IbGibSpaceAny } from '../common/witnesses/spaces/space-base-v1'; @@ -97,10 +97,16 @@ export class IbGibPage extends IbgibComponentBase @Input() autosync: boolean = false; + @Input() + downloadingPic: boolean = false; + @Input() get autoRefresh(): boolean { return !this.paused; } set autoRefresh(value: boolean) { this.paused = value; } + @Input() + actionBarHeightPerPlatform: string = '55px !important'; + constructor( protected common: CommonService, protected ref: ChangeDetectorRef, @@ -114,6 +120,9 @@ export class IbGibPage extends IbgibComponentBase if (logalot) { console.log(`${lc} called.`) } try { this.subscribeParamMap(); + if (this.common.platform.is('mobileweb')) { + this.actionBarHeightPerPlatform = '110px !important'; + } super.ngOnInit(); } catch (error) { console.error(`${lc} ${error.message}`); @@ -226,12 +235,24 @@ export class IbGibPage extends IbgibComponentBase const prompt = getFnPrompt(); try { if (logalot) { console.log(`${lc} starting...`); } + const alert = getFnAlert(); + const confirm = getFnConfirm(); + const resConfirm = await confirm({ + title: 'Not implemented well on Android', + msg: `On Android, this will download the file as base64-encoded data. This does not display correctly on some (all?) Android device galleries.\n\nDo you want to proceed?` + }); + + if (!resConfirm) { + await alert({title: 'K', msg: 'Cancelled'}); + return; // <<<< returns + } + + this.downloadingPic = true; const picIbGib = >this.ibGib; const { data } = picIbGib; if (!this.item?.picSrc) { throw new Error(`this.item?.picSrc is falsy...pic not loaded or not a pic? (E: e6c361e80cbd0f6221c51cd3f4b4fb22)`); } if (!data.binHash) { throw new Error(`invalid pic data. binHash is falsy. (E: f2ac49f8451c2054833069aac44b8222)`); } - debugger; // remove data.filename to test this workflow const filename = data.filename || await prompt({ @@ -239,7 +260,7 @@ export class IbGibPage extends IbgibComponentBase msg: `What's the filename? ${data.filename ? `Leave blank to default to ${data.filename}`: ''}`, }) || data.binHash; - debugger; // remove data.ext to test this workflow + const ext = data.ext || await prompt({ @@ -247,7 +268,6 @@ export class IbGibPage extends IbgibComponentBase msg: `What's the file extension? Leave blank to default to ${c.DEFAULT_PIC_FILE_EXTENSION}`, }) || c.DEFAULT_PIC_FILE_EXTENSION; - debugger; // remove data.ext to test this workflow const filenameWithExt = `${filename}.${ext}`; @@ -259,26 +279,44 @@ export class IbGibPage extends IbgibComponentBase } // check to see if file already exists existing file - let path = filenameWithExt; + let path: string; + let dirPath: string = `${c.IBGIB_BASE_SUBPATH}/${c.IBGIB_DOWNLOADED_PICS_SUBPATH}`; + await ensureDirPath({dirPath, directory}); let suffixNum: number = 0; - let exists: boolean; + let pathAlreadyExists: boolean; + let attempts = 0; do { - exists = await pathExists({ + suffixNum++; + path = suffixNum === 1 ? + `${dirPath}/${filenameWithExt}` : + `${dirPath}/${filename}(${suffixNum}).${ext}`; + pathAlreadyExists = await pathExists({ path, directory, encoding: FilesystemEncoding.UTF8, }); + attempts++; + } while (pathAlreadyExists && attempts < 10); // just hard-coding this here, very edgy edge case. - if (exists) { - suffixNum++; - path = `${filename}(${suffixNum}).${ext}`; - } - } while (exists); + if (pathAlreadyExists) { throw new Error(`Tried 10 times and path ${filenameWithExt} (1-10) already exists. Last path tried: ${path}. (E: 09881b77a62747fbb0c2dd5057ae970a)`); } + + // path does not exist, so write it with our picture data. + const dataToWrite = this.item.picSrc.replace(/^data\:image\/(jpeg|jpg|png)\;base64\,/i, ''); + // THIS DOES NOT "WORK". It successfully downloads the base64 encoded + // string, but on my android testing this does not show the picture. I've + // wasted enough time on this for now. + + await writeFile({path, data: dataToWrite, directory: FilesystemDirectory.Documents}); + + await h.delay(100); // so user can see visually that write happened + await getFnAlert()({title: 'file downloaded', msg: `Successfully downloaded to ${path} in ${directory}.`}); } catch (error) { console.error(`${lc} ${error.message}`); await alert({title: 'download pic...', msg: `hmm, something went wrong. error: ${error.message}`}); } finally { if (logalot) { console.log(`${lc} complete.`); } + this.downloadingPic = false; + setTimeout(() => this.ref.detectChanges()); } } diff --git a/ionic-gib/src/app/services/common.service.ts b/ionic-gib/src/app/services/common.service.ts index 742772ea..a1f00454 100644 --- a/ionic-gib/src/app/services/common.service.ts +++ b/ionic-gib/src/app/services/common.service.ts @@ -1,4 +1,4 @@ -import { ModalController, } from '@ionic/angular'; +import { ModalController, Platform, } from '@ionic/angular'; import { Injectable, Inject } from '@angular/core'; import { IbgibsService } from './ibgibs.service'; @@ -77,6 +77,7 @@ export class CommonService { // public files: FilesService, public modalController: ModalController, @Inject('IbgibNav') public nav: IbgibNav, + public platform: Platform, ) { } }