I have developed an app that allows you to open and edit Office files (.docx) in Word. In order for the app and Word to have appropriate permissions on iOS, I set the option "LSSupportsOpeningDocumentsInPlace" to YES in my info.plist file.
What I also want is that I can share files directly from the Files app into my app. However, with iOS the option "Share to 'myApp'" does not work anymore as soon as I set "LSSupportsOpeningDocumentsInPlace" to YES but only "Open in 'myApp'". And that's exactly where the problem lies when I pass the passed file path to Plugin File.
Without "LSSupportsOpeningDocumentsInPlace" I get the following path:
file: ///private/var/mobile/Containers/Data/Application/300F9E3A-2E17-4330-8F88-12855269CCA8/tmp/com.my.app-Inbox/Dokument.docx
The plugin file recognizes the path and I can do anything else with the file I want.
But with set option "LSSupportsOpeningDocumentsInPlace" to YES I get the following path:
file: ///private/var/mobile/Containers/Data/Application/304CFCDB-227B-4149-9F87-078B341F7A00/Documents/Dokument.docx
And the plugin file returns the error: "NOT_FOUND_ERROR"
Is there a way that works both? The parts function from FILES and the permission to edit documents out of the app?
EDIT:
import {File} from '#ionic-native/file'
...
constructor(public file: File) {
}
this.deeplinks.routeWithNavController(this.nav, {}).subscribe(
(match) => {
this.storeFile(match.$link.url);
}
}, (nomatch) => {
});
storeFile(filepath) {
this.file.resolveLocalFilesystemUrl(filepath)
.then((entry) => {
console.log(entry);
})
.catch((e) => {
console.log(e)
})
}
EDIT 2:
storeFile(filepath) {
this.file.resolveDirectoryUrl(path1)
.then((entry) => {
console.log('+++++++++++++++', entry);
this.file.checkDir(entry.nativeURL, '')
.then((dir) => {
console.log('+++++++++++++++ dir', dir);
this.file.listDir(entry.nativeURL, '')
.then((list) => {
console.log('+++++++++++++++ list', list);
})
.catch((e) => {
console.log('--------------- list', e) // <--- NOT_FOUND_ERROR
})
})
.catch((e) => {
console.log('--------------- dir', e)
})
}, (e) => {
console.log('---------------', e)
});
}
Related
I am trying to delete an object within a firebase firestore database. This was built in react native expo. When I run the code shown below, the console displays "Doc deleted", however, The object I meant to delete still shows in firebase as well as within my applicaton. Any advice would be greatly appreciated.
async function deleteProperty() {
await firebase.firestore().collection("Properties").get().then((documentSnapshot => {
documentSnapshot.forEach((doc) => {
if (doc.data().address == route.params.address) {
firebase.firestore().collection("Properties").doc().delete().then(() => {
console.log("Doc deleted")
}).catch((error) => {
console.error("Error removing document: ", error)
})
}
})
}))
}
It looks like you have to pass document id to doc() specifically.
firebase.firestore().collection("Properties").doc(doc.id).delete().then(() => {
console.log("Doc deleted")
}).catch((error) => {
console.error("Error removing document: ", error)
})
ref: https://firebase.google.com/docs/firestore/manage-data/delete-data#web-version-8
I want to test my Electron application but I feel this is harder than I expected!
Just a simple thing as using the open file dialog seems impossible from what I've seen when I looked around a while!
Is it at all possible, or can I mock this behavior somehow?
My application adds the selected files to a file list and shows some result in a grid. If I can't open files I wont get the grid and can't test if it behaves as expected.
How should I approach this issue if I can't use the file dialog?
This is my test setup:
import { Application } from "spectron";
import { expect } from "chai";
describe("Application", function() {
this.timeout(10000);
let app: Application;
let browser: any;
before(async () => {
app = new Application({
path: electronPath,
args: [appPath],
});
await app.start();
browser = app.client;
await browser.waitUntilWindowLoaded();
});
after(() => {
await app.stop();
});
it("Starts application", async () => {
const count = await browser.getWindowCount();
expect(count).to.equal(1);
});
it("should add files", async function() {
await browser.click("#block-container > div.button-row > div:nth-child(1) > button:nth-child(1)");
// ???
});
});
And this is the addFiles method:
public addFiles() {
const selectedFiles: string[] = this.electronService.remote.dialog.showOpenDialogSync({
title: "Add files",
properties: ["openFile", "multiSelections"]
});
...
}
I am trying to add Universal Linking to a Cordova App using the ionic-plugin-deeplinks plugin.
According to this issue query parameters should work out of the box.
Universal Links for me work correctly except for links with query parameters.
Eg. https://my-site.com/?olddeeplinking=resetpassword&token=123
When I click on the link in an email the queryString field is always an empty string.
Am I missing something, do I need to enable the plugins to detect query params?
Here is the code that I'm using:
const deepLinkRoutes = {
'/user/login': {
action: 'showLogin',
resetUrl: '/',
},
'/user/forgot-password': {
action: 'showForgotPassword',
resetUrl: '/',
},
...
};
export const _getIonicRoutes = () => Object.keys(deepLinkRoutes)
.reduce((links, route) => {
links[route] = { target: '', parent: '' };
return links;
}, {});
export const handleUniversalLinks = () => {
const ionicRoutes = _getIonicRoutes();
const sy = obj => JSON.stringify(obj);
const matchFn = ({ $link, $route, $args }) => {
console.log('Successfully matched route', $link, $route, $args);
alert(`Successfully matched route: ${sy($link)}, ${sy($route)}, ${sy($args)}`);
return history.push($link.path);
};
const noMatchFn = ({ $link, $route, $args }) => {
console.log('NOT Successfully matched route', $link, $route, $args);
alert(`NOT Successfully matched route: ${sy($link)}, ${sy($route)}, ${sy($args)}`);
return history.push($link.path);
};
window.IonicDeeplink.route(ionicRoutes, matchFn, noMatchFn);
};
UPDATE:
It looks like the intent received on Android is always /user/login even though the Universal Link does not have it. What could be causing that?
2019-10-21 17:22:47.107 30389-30389/? D/MessageViewGestureDetector: HitTestResult type=7, extra=https://nj.us.gpd.my_company-dev.com/user/login
2019-10-21 17:22:47.139 1128-1183/? I/ActivityManager: START u0 {act=android.intent.action.VIEW dat=https://nj.us.gpd.williamhill-dev.com/... cmp=us.my_company.nj.sports.gpd/.MainActivity} from uid 10147
A clue:
It looks like the deeplinks plugin is using window.location.href to detect the query parameter.
Since I am using cordova-plugin-ionic-webview the href is always the alias used for localhost of the Ionic engine serving the App contents, so the query parameters are never found.
Deeplinks plugin code:
https://github.com/ionic-team/ionic-plugin-deeplinks/blob/master/src/browser/DeeplinkProxy.js#L40
function locationToData(l) {
return {
url: l.href,
path: l.pathname,
host: l.hostname,
fragment: l.hash,
scheme: parseSchemeFromUrl(l.href),
queryString: parseQueryStringFromUrl(l.href)
}
}
onDeepLink: function(callback) {
// Try the first deeplink route
setTimeout(function() {
callback && callback(locationToData(window.location), {
keepCallback: true
});
})
// ...
}
This is the problem, not sure on the solution yet though.
I am able to create pdf in my ionic app and if I run the app in chrome it opens perfectly. However if I install my app on the android device it doesn't open. Below is my code. Can someone please help me if I have to do something extra to open it on device. I want to open it with default pdf application on device.
pdfMake.createPdf(dd).open();
Ok. After banging my head on wall for 3 days I finally found the solution and sharing here so that other people who are facing this issue can get help. I am creating pdf and saving it using cordova file plugin. After successful save I am opening it in default application using cordova file opener plugin. Below is my code.
pdfMake.createPdf(YOUR_DEFINITION_HERE).getBlob(buffer => {
this.file.resolveDirectoryUrl(this.file.externalRootDirectory)
.then(dirEntry => {
this.file.getFile(dirEntry, 'test1.pdf', { create: true })
.then(fileEntry => {
fileEntry.createWriter(writer => {
writer.onwrite = () => {
this.fileOpener.open(fileEntry.toURL(), 'application/pdf')
.then(res => { })
.catch(err => {
const alert = this.alertCtrl.create({ message:
err.message, buttons: ['Ok'] });
alert.present();
});
}
writer.write(buffer);
})
})
.catch(err => {
const alert = this.alertCtrl.create({ message: err, buttons: ['Ok'] });
alert.present();
});
})
.catch(err => {
const alert = this.alertCtrl.create({ message: err, buttons: ['Ok']
});
alert.present();
});
});
I'm currently trying to implement some functionality in my react native app where I use information stored locally if the device is offline, and perform a fetch if the device is online.
I used NetInfo after reading this How to handle network failure in React-Native, when network is off, but unfortunately I ran into an error where NetInfo always returns offline. I found this github issue, which recommended that I change the host in RCTReachability.m from 'htpp://apple.com' to 'apple.com'. However, I couldn't find a file with that name in the project directory. Instead I found the only mention of 'apple.com' in any file, which was in RCTNetInfo.m, which was in the correct form.
Does anybody know a way to fix this problem? Or possibly a different way to go about performing one action if the device is online, and another if the device is offline?
Here's the relevant code:
fetchData() {
NetInfo.isConnected.fetch().done((isConnected) => {
console.log('First, is ' + (isConnected ? 'online' : 'offline'));
if ( isConnected )
{
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
store.save('contacts', responseData.feed.entry)
.then(() => store.get('contacts'))
.then((contacts) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(contacts),
isLoading: false
});
})
})
.catch((error) => { console.error(error); });
}
else
{
store.get('contacts')
.then(contacts => {
if (contacts == null)
{
this.setState({
dataSource: this.state.dataSource.cloneWithRows(CONTACT_DATA),
isLoading: false
});
}
else
{
this.setState({
dataSource: this.state.dataSource.cloneWithRows(contacts),
isLoading: false
});
}
})
}
});
}