intent error on android solved
This commit is contained in:
parent
b05a779c09
commit
925c231db4
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1420"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1420"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "65B5150F29BB4AB8005DC684"
|
||||
BuildableName = "upload.appex"
|
||||
BlueprintName = "upload"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "1"
|
||||
BundleIdentifier = "gcube.workspace.starter"
|
||||
RemotePath = "/Users/lucio/Library/Developer/CoreSimulator/Devices/F17E9BEA-B875-4A5C-A276-00EF1DC47FE7/data/Containers/Bundle/Application/6B87E654-9A60-4478-927C-BFC257A7CCAF/App.app">
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "504EC3031FED79650016851F"
|
||||
BuildableName = "App.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:App.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Share View Controller-->
|
||||
<scene sceneID="ceB-am-kn3">
|
||||
<objects>
|
||||
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationRule</key>
|
||||
<string>TRUEPREDICATE</string>
|
||||
</dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
<string>MainInterface</string>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.share-services</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,192 @@
|
|||
//
|
||||
// ShareViewController.swift
|
||||
// upload
|
||||
//
|
||||
// Created by Lucio Lelii on 10/03/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Social
|
||||
import MobileCoreServices
|
||||
import Foundation.NSURLSession
|
||||
|
||||
class ShareItem {
|
||||
public var title: String?
|
||||
public var type: String?
|
||||
public var url: String?
|
||||
public var webPath: String?
|
||||
}
|
||||
|
||||
class ShareViewController: UIViewController {
|
||||
private var shareItems: [ShareItem] = []
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
print("did appear called");
|
||||
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
|
||||
}
|
||||
|
||||
override public func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
shareItems.removeAll()
|
||||
let extensionItem = extensionContext?.inputItems[0] as! NSExtensionItem
|
||||
Task {
|
||||
try await withThrowingTaskGroup(
|
||||
of: ShareItem.self,
|
||||
body: { taskGroup in
|
||||
for attachment in extensionItem.attachments! {
|
||||
if attachment.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
|
||||
taskGroup.addTask {
|
||||
return try await self.handleTypeUrl(attachment)
|
||||
}
|
||||
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
|
||||
taskGroup.addTask {
|
||||
return try await self.handleTypeText(attachment)
|
||||
}
|
||||
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) {
|
||||
taskGroup.addTask {
|
||||
return try await self.handleTypeMovie(attachment)
|
||||
}
|
||||
} else if attachment.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
|
||||
taskGroup.addTask {
|
||||
return try await self.handleTypeImage(attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
for try await item in taskGroup {
|
||||
self.shareItems.append(item)
|
||||
}
|
||||
})
|
||||
self.sendData()
|
||||
}
|
||||
}
|
||||
|
||||
private func sendData() {
|
||||
let queryItems = shareItems.map {
|
||||
[
|
||||
URLQueryItem(
|
||||
name: "title",
|
||||
value: $0.title?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
|
||||
URLQueryItem(name: "description", value: ""),
|
||||
URLQueryItem(
|
||||
name: "type",
|
||||
value: $0.type?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
|
||||
URLQueryItem(
|
||||
name: "url",
|
||||
value: $0.url?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
|
||||
URLQueryItem(
|
||||
name: "webPath",
|
||||
value: $0.webPath?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? "")
|
||||
]
|
||||
}.flatMap({ $0 })
|
||||
var urlComps = URLComponents(string: "d4sworkspace://share-input")!
|
||||
urlComps.queryItems = queryItems
|
||||
var opened = openURL(urlComps.url!)
|
||||
print("sending data %s",opened);
|
||||
}
|
||||
|
||||
fileprivate func createSharedFileUrl(_ url: URL?) -> String {
|
||||
let fileManager = FileManager.default
|
||||
print("share url: " + url!.absoluteString)
|
||||
let copyFileUrl =
|
||||
fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.gcube.workspace")!
|
||||
.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! + url!
|
||||
.lastPathComponent.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
|
||||
try? Data(contentsOf: url!).write(to: URL(string: copyFileUrl)!)
|
||||
|
||||
return copyFileUrl
|
||||
}
|
||||
|
||||
func saveScreenshot(_ image: UIImage) -> String {
|
||||
let fileManager = FileManager.default
|
||||
|
||||
let copyFileUrl =
|
||||
fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.gcube.workspace")!
|
||||
.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
|
||||
+ "/screenshot.png"
|
||||
do {
|
||||
try image.pngData()?.write(to: URL(string: copyFileUrl)!)
|
||||
return copyFileUrl
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func handleTypeUrl(_ attachment: NSItemProvider)
|
||||
async throws -> ShareItem
|
||||
{
|
||||
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil)
|
||||
let url = results as! URL?
|
||||
let shareItem: ShareItem = ShareItem()
|
||||
|
||||
if url!.isFileURL {
|
||||
shareItem.title = url!.lastPathComponent
|
||||
shareItem.type = "application/" + url!.pathExtension.lowercased()
|
||||
shareItem.url = createSharedFileUrl(url)
|
||||
shareItem.webPath = "capacitor://localhost/_capacitor_file_" + URL(string: shareItem.url ?? "")!.path
|
||||
} else {
|
||||
shareItem.title = url!.absoluteString
|
||||
shareItem.url = url!.absoluteString
|
||||
shareItem.webPath = url!.absoluteString
|
||||
shareItem.type = "text/plain"
|
||||
}
|
||||
return shareItem
|
||||
}
|
||||
|
||||
fileprivate func handleTypeText(_ attachment: NSItemProvider)
|
||||
async throws -> ShareItem
|
||||
{
|
||||
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeText as String, options: nil)
|
||||
let shareItem: ShareItem = ShareItem()
|
||||
let text = results as! String
|
||||
shareItem.title = text
|
||||
shareItem.type = "text/plain"
|
||||
return shareItem
|
||||
}
|
||||
|
||||
fileprivate func handleTypeMovie(_ attachment: NSItemProvider)
|
||||
async throws -> ShareItem
|
||||
{
|
||||
let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeMovie as String, options: nil)
|
||||
let shareItem: ShareItem = ShareItem()
|
||||
let url = results as! URL?
|
||||
shareItem.title = url!.lastPathComponent
|
||||
shareItem.type = "video/" + url!.pathExtension.lowercased()
|
||||
shareItem.url = createSharedFileUrl(url)
|
||||
shareItem.webPath = "capacitor://localhost/_capacitor_file_" + URL(string: shareItem.url ?? "")!.path
|
||||
return shareItem
|
||||
}
|
||||
|
||||
fileprivate func handleTypeImage(_ attachment: NSItemProvider)
|
||||
async throws -> ShareItem
|
||||
{
|
||||
let data = try await attachment.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil)
|
||||
let shareItem: ShareItem = ShareItem()
|
||||
switch data {
|
||||
case let image as UIImage:
|
||||
shareItem.title = "screenshot"
|
||||
shareItem.type = "image/png"
|
||||
shareItem.url = self.saveScreenshot(image)
|
||||
shareItem.webPath = "capacitor://localhost/_capacitor_file_" + URL(string: shareItem.url ?? "")!.path
|
||||
case let url as URL:
|
||||
shareItem.title = url.lastPathComponent
|
||||
shareItem.type = "image/" + url.pathExtension.lowercased()
|
||||
shareItem.url = self.createSharedFileUrl(url)
|
||||
shareItem.webPath = "capacitor://localhost/_capacitor_file_" + URL(string: shareItem.url ?? "")!.path
|
||||
default:
|
||||
print("Unexpected image data:", type(of: data))
|
||||
}
|
||||
return shareItem
|
||||
}
|
||||
|
||||
@objc func openURL(_ url: URL) -> Bool {
|
||||
var responder: UIResponder? = self
|
||||
while responder != nil {
|
||||
if let application = responder as? UIApplication {
|
||||
return application.perform(#selector(openURL(_:)), with: url) != nil
|
||||
}
|
||||
responder = responder?.next
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { ShareExtension } from "capacitor-share-extension";
|
||||
import { D4sIntentService } from "../d4s-intent.service";
|
||||
|
||||
export function initializeIntent(d4sIntent: D4sIntentService) {
|
||||
|
||||
return () => {
|
||||
window.addEventListener('sendIntentReceived', () => {
|
||||
console.log("event fired");
|
||||
d4sIntent.checkIntent();
|
||||
});
|
||||
d4sIntent.checkIntent();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import { AlertController } from "@ionic/angular";
|
||||
|
||||
/**
|
||||
* Format bytes as human-readable text.
|
||||
*
|
||||
* @param bytes Number of bytes.
|
||||
* @param si True to use metric (SI) units, aka powers of 1000. False to use
|
||||
* binary (IEC), aka powers of 1024.
|
||||
* @param dp Number of decimal places to display.
|
||||
*
|
||||
* @return Formatted string.
|
||||
*/
|
||||
export function humanFileSize(bytes:number, si=true, dp=1) {
|
||||
const thresh = si ? 1000 : 1024;
|
||||
|
||||
if (Math.abs(bytes) < thresh) {
|
||||
return bytes + ' B';
|
||||
}
|
||||
|
||||
const units = si
|
||||
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
||||
let u = -1;
|
||||
const r = 10**dp;
|
||||
|
||||
do {
|
||||
bytes /= thresh;
|
||||
++u;
|
||||
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
|
||||
|
||||
|
||||
return bytes.toFixed(dp) + ' ' + units[u];
|
||||
}
|
||||
|
||||
|
||||
export async function presentConnectionAlert(err: string, alertCtrl: AlertController){
|
||||
const alert = await alertCtrl.create({
|
||||
header: 'Connection ERROR',
|
||||
message: err,
|
||||
buttons: ['OK'],
|
||||
});
|
||||
await alert.present();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { D4sIntentService } from './d4s-intent.service';
|
||||
|
||||
describe('D4sIntentService', () => {
|
||||
let service: D4sIntentService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(D4sIntentService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,61 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ModalController, ModalOptions, ToastController } from '@ionic/angular';
|
||||
import { ShareExtension } from 'capacitor-share-extension';
|
||||
import { EventService } from './event.service';
|
||||
import { UploadFile } from './model/actions/upload-file';
|
||||
import { StoragehubService } from './storagehub.service';
|
||||
import { UploaderInfoService } from './uploader-info.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class D4sIntentService {
|
||||
|
||||
constructor(private modalCtrl: ModalController,
|
||||
private toastController: ToastController,
|
||||
private storagehub: StoragehubService,
|
||||
private uploaderInfo: UploaderInfoService,
|
||||
private event: EventService) { }
|
||||
|
||||
|
||||
async checkIntent() {
|
||||
try {
|
||||
const result: any = await ShareExtension.checkSendIntentReceived();
|
||||
/* sample result::
|
||||
{ payload: [
|
||||
{
|
||||
"type":"image%2Fjpg",
|
||||
"description":"",
|
||||
"title":"IMG_0002.JPG",
|
||||
// url contains a full, platform-specific file URL that can be read later using the Filsystem API.
|
||||
"url":"file%3A%2F%2F%2FUsers%2Fcalvinho%2FLibrary%2FDeveloper%2FCoreSimulator%2FDevices%2FE4C13502-3A0B-4DF4-98ED-9F31DDF03672%2Fdata%2FContainers%2FShared%2FAppGroup%2FF41DC1F5-54D7-4EC5-9785-5248BAE06588%2FIMG_0002.JPG",
|
||||
// webPath returns a path that can be used to set the src attribute of an image for efficient loading and rendering.
|
||||
"webPath":"capacitor%3A%2F%2Flocalhost%2F_capacitor_file_%2FUsers%2Fcalvinho%2FLibrary%2FDeveloper%2FCoreSimulator%2FDevices%2FE4C13502-3A0B-4DF4-98ED-9F31DDF03672%2Fdata%2FContainers%2FShared%2FAppGroup%2FF41DC1F5-54D7-4EC5-9785-5248BAE06588%2FIMG_0002.JPG",
|
||||
}]
|
||||
}
|
||||
*/
|
||||
if (result && result.payload && result.payload.length) {
|
||||
console.log('Intent received: ', JSON.stringify(result.payload[0]));
|
||||
var modalOptions: ModalOptions = new UploadFile().getModalOptions(this.storagehub, this.uploaderInfo, result.payload[0],
|
||||
(id : string) =>{
|
||||
this.event.ReloadEvent.emit(id);
|
||||
ShareExtension.finish();
|
||||
}, (text: string) => this.presentToast(text));
|
||||
let modal = await this.modalCtrl.create(modalOptions);
|
||||
await modal.present();
|
||||
} else {
|
||||
console.log("nothing received");
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
async presentToast(text: string) {
|
||||
const toast = await this.toastController.create({
|
||||
message: text,
|
||||
duration: 1500
|
||||
});
|
||||
await toast.present();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EventService } from './event.service';
|
||||
|
||||
describe('EventService', () => {
|
||||
let service: EventService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(EventService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import { EventEmitter, Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EventService {
|
||||
|
||||
ReloadEvent = new EventEmitter<string>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
import { AlertController, LoadingController } from "@ionic/angular";
|
||||
import { WSItem } from "../ws-item";
|
||||
import { StoragehubService } from "src/app/storagehub.service";
|
||||
import { Directory, Filesystem } from "@capacitor/filesystem";
|
||||
import { FileOpener } from "@awesome-cordova-plugins/file-opener/ngx";
|
||||
import { App } from '@capacitor/app';
|
||||
import { isPlatform } from '@ionic/angular';
|
||||
import { presentConnectionAlert } from "src/app/_helper/utils";
|
||||
|
||||
|
||||
export class OpenFile {
|
||||
|
||||
pluginListener: any;
|
||||
|
||||
item: WSItem;
|
||||
|
||||
constructor(item: WSItem) {
|
||||
this.item = item;
|
||||
if (isPlatform("android")) {
|
||||
App.addListener('resume', () => {
|
||||
Filesystem.deleteFile(
|
||||
{
|
||||
path: item.getTitle(),
|
||||
directory: Directory.Documents
|
||||
}).then(() => console.log("file deleted"));
|
||||
this.pluginListener?.remove();
|
||||
}).then((handler) => this.pluginListener = handler);
|
||||
}
|
||||
}
|
||||
|
||||
async open(storageHub: StoragehubService, fileOpener: FileOpener, loadingCtrl: LoadingController, alertCtrl: AlertController) {
|
||||
const size = this.item.item.content?.size;
|
||||
if (!size || size / 1000000 > 20) {
|
||||
this.presentAlert(alertCtrl);
|
||||
return;
|
||||
}
|
||||
|
||||
this.showLoading(loadingCtrl);
|
||||
storageHub.downloadFile(this.item.item.id).then(obs => obs.subscribe({
|
||||
next: async blob => {
|
||||
const base64 = await this.blobToBase64(blob) as string;
|
||||
const fileWrited = await Filesystem.writeFile({
|
||||
path: this.item.getTitle(),
|
||||
data: base64,
|
||||
directory: Directory.Documents
|
||||
});
|
||||
|
||||
const mimeType = this.item.item.content?.mimeType;
|
||||
fileOpener.open(fileWrited.uri, mimeType ? mimeType : "application/octet-stream").then(() => {
|
||||
loadingCtrl.dismiss();
|
||||
if (isPlatform("ios"))
|
||||
Filesystem.deleteFile(
|
||||
{
|
||||
path: this.item.getTitle(),
|
||||
directory: Directory.Documents
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
},
|
||||
error: (err) => {
|
||||
loadingCtrl.dismiss();
|
||||
this.pluginListener?.remove();
|
||||
presentConnectionAlert(err, alertCtrl);
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
async presentAlert(alertCtrl: AlertController) {
|
||||
const alert = await alertCtrl.create({
|
||||
header: 'Alert',
|
||||
message: 'File too big to be opeend here!',
|
||||
buttons: ['OK'],
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async showLoading(loadingCtrl: LoadingController) {
|
||||
const loading = await loadingCtrl.create({
|
||||
message: 'Loading...',
|
||||
duration: 20000,
|
||||
spinner: 'circles',
|
||||
});
|
||||
|
||||
loading.present();
|
||||
return loading;
|
||||
}
|
||||
|
||||
|
||||
blobToBase64(blob: Blob) {
|
||||
return new Promise((resolve, _) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(reader.result);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
import { ModalOptions } from "@ionic/angular";
|
||||
import { StoragehubService } from "src/app/storagehub.service";
|
||||
import { WsViewerComponent } from "src/app/ws-viewer/ws-viewer.component";
|
||||
import { WSItem } from "../ws-item";
|
||||
import { Filesystem } from "@capacitor/filesystem";
|
||||
import { UploaderInfoService } from "src/app/uploader-info.service";
|
||||
|
||||
export class UploadFile {
|
||||
|
||||
|
||||
|
||||
getModalOptions(storagehub: StoragehubService, uploaderInfo: UploaderInfoService, data: any, reload: Function, notify: Function): ModalOptions {
|
||||
return {
|
||||
component: WsViewerComponent,
|
||||
componentProps: {
|
||||
finishLabel: "Upload here",
|
||||
title: "Select destination folder",
|
||||
notClickableIds: [],
|
||||
notSelectableIds: [],
|
||||
onSelected: (destinationItem: WSItem) => {
|
||||
const itemId = destinationItem.item.id;
|
||||
uploaderInfo.uploadStarted(itemId, data.title);
|
||||
this.actionHandler(destinationItem, data, storagehub).then( obs => obs.subscribe({
|
||||
next: () => {},
|
||||
error: err => uploaderInfo.uploadFinished(itemId, data.title),
|
||||
complete: () => {
|
||||
notify(`uploaded file ${data.title}`);
|
||||
uploaderInfo.uploadFinished(itemId, data.title),
|
||||
reload(itemId);
|
||||
},
|
||||
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
async actionHandler(destinationItem: WSItem, result: any, storagehub: StoragehubService) {
|
||||
const pathDecodedWebPath = decodeURIComponent(result.webPath);
|
||||
|
||||
const file = await fetch(pathDecodedWebPath)
|
||||
.then(res => res.blob()) // Gets the response and returns it as a blob
|
||||
.then(blob => { return new File([blob], result.title)});
|
||||
|
||||
console.log("before uploading file ");
|
||||
return storagehub.uploadFile(destinationItem.item.id, result.title, file);
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return "UploadFile";
|
||||
}
|
||||
getActionType(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UploaderInfoService } from './uploader-info.service';
|
||||
|
||||
describe('UploaderInfoService', () => {
|
||||
let service: UploaderInfoService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(UploaderInfoService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UploaderInfoService {
|
||||
|
||||
myMap = new Map<string, string[]>();
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
uploadStarted(itemId: string, fileName: string) {
|
||||
var values = this.myMap.get(itemId);
|
||||
if (!values)
|
||||
values = [fileName];
|
||||
else
|
||||
values.push(fileName);
|
||||
this.myMap.set(itemId, values);
|
||||
}
|
||||
|
||||
uploadFinished(itemId: string , fileName: string) {
|
||||
var values = this.myMap.get(itemId);
|
||||
var newValues: string[] = [];
|
||||
values?.filter(val => val!= fileName).forEach(val => newValues?.push(val))
|
||||
if (newValues)
|
||||
if (newValues.length>0)
|
||||
this.myMap.set(itemId, newValues);
|
||||
else this.myMap.delete(itemId);
|
||||
}
|
||||
|
||||
getUnderUpload(itemId: string): string[]{
|
||||
var values = this.myMap.get(itemId);
|
||||
//console.log(`get upload called with array ${values}`);
|
||||
return values? values : [];
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue