1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-27 20:29:45 +02:00

Compare commits

..

14 Commits

Author SHA1 Message Date
Laurent Cozic
28e00fdf2e Android release v1.2.5 2020-10-08 12:56:12 +01:00
Laurent Cozic
3bd0656eab Android release v1.2.4 2020-10-08 12:51:48 +01:00
Laurent Cozic
e9af71dd76 Android: Reverted app to singleTop launch mode and fixed potential crash when sharing with app 2020-10-08 11:49:39 +01:00
Laurent Cozic
73b33e8e32 Android: Fixes #3800: Simplify initialisation code to prevent sharing
with app to create multiple instance of app and break settings.

Revert "Mobile: Add startup screen to show progress of db migration"

This reverts commit 569355a318.
2020-10-08 11:35:29 +01:00
Laurent Cozic
c2c7efee91 Desktop: Also make toggle button area wider 2020-10-07 21:03:56 +01:00
Laurent Cozic
0836fca822 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-10-07 20:59:50 +01:00
Laurent Cozic
566df5039c Desktop: Fixes #3876: Notebooks and tags click area was too narrow 2020-10-07 20:58:43 +01:00
Laurent Cozic
559655bf33 Android release v1.2.3 2020-10-06 13:06:48 +01:00
Laurent Cozic
0eab23fbcf Android: Set app launchMode to singleInstance to try to fix lost settings issue 2020-10-06 13:02:41 +01:00
Laurent Cozic
f334f4f487 All: Improved handling of database migration failures 2020-10-06 12:47:33 +01:00
Laurent Cozic
00057da17d Electron release v1.2.4 2020-09-30 08:16:46 +01:00
Laurent Cozic
0a05464013 Desktop: Regression: Context menu on sidebar did not work anymore 2020-09-30 08:16:20 +01:00
Laurent Cozic
9ebb574059 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-09-29 14:27:33 +01:00
Laurent Cozic
d29c3c2466 Desktop: Regression: Sidebar toggle button did not work anymore 2020-09-29 14:26:05 +01:00
15 changed files with 103 additions and 111 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -54,7 +54,7 @@ function ExpandIcon(props:any) {
function ExpandLink(props:any) {
return props.hasChildren ? (
<StyledExpandLink href="#" data-folder-id={props.folderId} onClick={props.onFolderToggleClick_}>
<StyledExpandLink href="#" data-folder-id={props.folderId} onClick={props.onClick}>
<ExpandIcon themeId={props.themeId} isVisible={true} isExpanded={props.isExpanded}/>
</StyledExpandLink>
) : (
@@ -115,17 +115,9 @@ class SideBarComponent extends React.Component<Props, State> {
this.header_contextMenu = this.header_contextMenu.bind(this);
this.onAddFolderButtonClick = this.onAddFolderButtonClick.bind(this);
this.folderItem_click = this.folderItem_click.bind(this);
this.itemContextMenu = this.itemContextMenu.bind(this);
}
// componentDidUpdate(prevProps:any, _prevState:any) {
// const props = this.props as any;
// for (const k in this.props) {
// if (prevProps[k] !== props[k]) {
// console.info('Props', k, props[k]);
// }
// }
// }
onFolderDragStart_(event:any) {
const folderId = event.currentTarget.getAttribute('data-folder-id');
if (!folderId) return;
@@ -412,7 +404,7 @@ class SideBarComponent extends React.Component<Props, State> {
selected={selected}
data-id={tag.id}
data-type={BaseModel.TYPE_TAG}
onContextMenu={(event:any) => this.itemContextMenu(event)}
onContextMenu={this.itemContextMenu}
onClick={() => {
this.tagItem_click(tag);
}}

View File

@@ -78,6 +78,7 @@ export const StyledListItemAnchor = styled.a`
flex: 1;
align-items: center;
user-select: none;
height: 100%;
`;
export const StyledExpandLink = styled.a`
@@ -91,6 +92,7 @@ export const StyledExpandLink = styled.a`
width: 16px;
max-width: 16px;
min-width: 16px;
height: 100%;
`;
export const StyledNoteCount = styled.div`

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.2.3",
"version": "1.2.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1535,7 +1535,7 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": false,
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"optional": true,
@@ -1701,7 +1701,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": false,
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true,
"optional": true
@@ -1817,7 +1817,7 @@
},
"tar": {
"version": "4.4.8",
"resolved": false,
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"dev": true,
"optional": true,
@@ -6122,7 +6122,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": false,
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true,
"optional": true

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.2.3",
"version": "1.2.4",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {

View File

@@ -125,8 +125,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097579
versionName "1.2.2"
versionCode 2097582
versionName "1.2.5"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -80,8 +80,19 @@
<!-- END RN-push-notitication -->
<!-- ============================= -->
<!-- 2018-12-16: Changed android:launchMode from "singleInstance" to "singleTop" for Firebase notification -->
<!-- Previously singleInstance was necessary to prevent multiple instance of the RN app from running at the same time, but maybe no longer needed. -->
<!--
2018-12-16: Changed android:launchMode from "singleInstance" to "singleTop" for Firebase notification
Previously singleInstance was necessary to prevent multiple instance of the RN app from running at the same time, but maybe no longer needed.
2020-10-06: Changed back again to "singleInstance" and notifications still seem to work. Changing to singleInstance
to try to fix this bug: https://discourse.joplinapp.org/t/joplin-android-app-looses-nextcloud-sync-settings/10997/6
Users would lose their settings, and it's possibly due to multiple instances of the app running at the same time, perhaps
due to sharing with the app. When checking the log, it would show "saving settings", then the app startup message, and after the app
has started, it would show "setting saved". So basically the app, or one instance of it, has started while settings were being saved
2020-10-08: Changed back again to "singleTop" as it has worked so far. The multiple instance bug was "fixed" in a different way
See ReactNativeClient/root.js for more info about the bug.
-->
<activity
android:name=".MainActivity"
android:label="@string/app_name"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -407,7 +407,9 @@ class NoteScreenComponent extends BaseScreenComponent {
this.saveActionQueue(this.state.note.id).processAllNow();
this.undoRedoService_.off('stackChange', this.undoRedoService_stackChange);
// It cannot theoretically be undefined, since componentDidMount should always be called before
// componentWillUnmount, but with React Native the impossible often becomes possible.
if (this.undoRedoService_) this.undoRedoService_.off('stackChange', this.undoRedoService_stackChange);
}
title_changeText(text) {

View File

@@ -3,7 +3,6 @@ const { Database } = require('lib/database.js');
const { sprintf } = require('sprintf-js');
const Resource = require('lib/models/Resource');
const { shim } = require('lib/shim.js');
const EventEmitter = require('events');
const structureSql = `
CREATE TABLE folders (
@@ -127,11 +126,6 @@ class JoplinDatabase extends Database {
this.version_ = null;
this.tableFieldNames_ = {};
this.extensionToLoad = './build/lib/sql-extensions/spellfix';
this.eventEmitter_ = new EventEmitter();
}
eventEmitter() {
return this.eventEmitter_;
}
initialized() {
@@ -349,6 +343,8 @@ class JoplinDatabase extends Database {
+ `Expected version: ${existingDatabaseVersions[existingDatabaseVersions.length - 1]}`);
}
this.logger().info(`Upgrading database from version ${fromVersion}`);
if (currentVersionIndex == existingDatabaseVersions.length - 1) return fromVersion;
let latestVersion = fromVersion;
@@ -359,8 +355,6 @@ class JoplinDatabase extends Database {
let queries = [];
this.eventEmitter_.emit('startMigration', { version: targetVersion });
if (targetVersion == 1) {
queries = this.wrapQueries(this.sqlStringToLines(structureSql));
}
@@ -856,18 +850,32 @@ class JoplinDatabase extends Database {
queries.push('CREATE VIRTUAL TABLE notes_spellfix USING spellfix1');
}
queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] });
const updateVersionQuery = { sql: 'UPDATE version SET version = ?', params: [targetVersion] };
queries.push(updateVersionQuery);
try {
await this.transactionExecBatch(queries);
} catch (error) {
// In some cases listed below, when the upgrade fail it is acceptable (a fallback will be used)
// and in those cases, even though it fails, we still want to set the version number so that the
// migration is not repeated on next upgrade.
let saveVersionAgain = false;
if (targetVersion === 15 || targetVersion === 18 || targetVersion === 33) {
this.logger().warn('Could not upgrade to database v15 or v18 or v33 - FTS feature will not be used', error);
saveVersionAgain = true;
} else if (targetVersion === 34) {
// this.logger().warn('Could not upgrade to database v34 - fuzzy search will not be used', error);
this.logger().warn('Could not upgrade to database v34 - fuzzy search will not be used', error);
saveVersionAgain = true;
} else {
throw error;
}
if (saveVersionAgain) {
this.logger().info('Migration failed with fallback and will not be repeated - saving version number');
await this.transactionExecBatch([updateVersionQuery]);
}
}
latestVersion = targetVersion;
@@ -933,10 +941,13 @@ class JoplinDatabase extends Database {
const version = !versionRow ? 0 : versionRow.version;
const tableFieldsVersion = !versionRow ? 0 : versionRow.table_fields_version;
this.version_ = version;
this.logger().info('Current database version', version);
this.logger().info('Current database version', versionRow);
const newVersion = await this.upgradeDatabase(version);
this.version_ = newVersion;
this.logger().info(`New version: ${newVersion}. Previously recorded version: ${tableFieldsVersion}`);
if (newVersion !== tableFieldsVersion) await this.refreshTableFields(newVersion);
this.tableFields_ = {};

View File

@@ -2,7 +2,7 @@ import setUpQuickActions from './setUpQuickActions';
import PluginAssetsLoader from './PluginAssetsLoader';
const React = require('react');
const { AppState, Keyboard, NativeModules, BackHandler, Animated, View, StatusBar, Text, Image } = require('react-native');
const { AppState, Keyboard, NativeModules, BackHandler, Animated, View, StatusBar } = require('react-native');
const SafeAreaView = require('lib/components/SafeAreaView');
const { connect, Provider } = require('react-redux');
const { BackButtonService } = require('lib/services/back-button.js');
@@ -376,7 +376,7 @@ function decryptionWorker_resourceMetadataButNotBlobDecrypted() {
ResourceFetcher.instance().scheduleAutoAddResources();
}
async function initialize(dispatch, messageHandler) {
async function initialize(dispatch) {
shimInit();
Setting.setConstant('env', __DEV__ ? 'dev' : 'prod');
@@ -415,13 +415,8 @@ async function initialize(dispatch, messageHandler) {
dbLogger.setLevel(Logger.LEVEL_INFO);
}
const db_startUpgrade = (event) => {
messageHandler(`Upgrading database to v${event.version}...`);
};
const db = new JoplinDatabase(new DatabaseDriverReactNative());
db.setLogger(dbLogger);
db.eventEmitter().on('startMigration', db_startUpgrade);
reg.setDb(db);
reg.dispatch = dispatch;
@@ -458,13 +453,9 @@ async function initialize(dispatch, messageHandler) {
// await db.clearForTesting();
}
db.eventEmitter().removeListener('startMigration', db_startUpgrade);
reg.logger().info('Database is ready.');
reg.logger().info('Loading settings...');
messageHandler('Initialising application...');
await loadKeychainServiceAndSettings(KeychainServiceDriverMobile);
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
@@ -611,7 +602,6 @@ class AppComponent extends React.Component {
this.state = {
sideMenuContentOpacity: new Animated.Value(0),
initMessage: '',
};
this.lastSyncStarted_ = defaultState.syncStarted;
@@ -625,52 +615,66 @@ class AppComponent extends React.Component {
};
}
componentDidMount() {
setTimeout(async () => {
// We run initialization code with a small delay to give time
// to the view to render "please wait" messages.
// 2020-10-08: It seems the initialisation code is quite fragile in general and should be kept simple.
// For example, adding a loading screen as was done in this commit: https://github.com/laurent22/joplin/commit/569355a3182bc12e50a54249882e3d68a72c2b28.
// had for effect that sharing with the app would create multiple instances of the app, thus breaking
// database access and so on. It's unclear why it happens and how to fix it but reverting that commit
// fixed the issue for now.
//
// Changing app launch mode doesn't help.
//
// It's possible that it's a bug in React Native, or perhaps the framework expects that the whole app can be
// mounted/unmounted or multiple ones can be running at the same time, but the app was not designed in this
// way.
//
// More reports and info about the multiple instance bug:
//
// https://github.com/laurent22/joplin/issues/3800
// https://github.com/laurent22/joplin/issues/3804
// https://github.com/laurent22/joplin/issues/3807
// https://discourse.joplinapp.org/t/webdav-config-encryption-config-randomly-lost-on-android/11364
// https://discourse.joplinapp.org/t/android-keeps-on-resetting-my-sync-and-theme/11443
async componentDidMount() {
if (this.props.appState == 'starting') {
this.props.dispatch({
type: 'APP_STATE_SET',
state: 'initializing',
});
await initialize(this.props.dispatch, (message) => {
this.setState({ initMessage: message });
});
BackButtonService.initialize(this.backButtonHandler_);
AlarmService.setInAppNotificationHandler(async (alarmId) => {
const alarm = await Alarm.load(alarmId);
const notification = await Alarm.makeNotification(alarm);
this.dropdownAlert_.alertWithType('info', notification.title, notification.body ? notification.body : '');
});
AppState.addEventListener('change', this.onAppStateChange_);
const sharedData = await ShareExtension.data();
if (sharedData) {
reg.logger().info('Received shared data');
if (this.props.selectedFolderId) {
handleShared(sharedData, this.props.selectedFolderId, this.props.dispatch);
} else {
reg.logger.info('Cannot handle share - default folder id is not set');
}
}
await initialize(this.props.dispatch);
this.props.dispatch({
type: 'APP_STATE_SET',
state: 'ready',
});
}, 100);
}
BackButtonService.initialize(this.backButtonHandler_);
AlarmService.setInAppNotificationHandler(async (alarmId) => {
const alarm = await Alarm.load(alarmId);
const notification = await Alarm.makeNotification(alarm);
this.dropdownAlert_.alertWithType('info', notification.title, notification.body ? notification.body : '');
});
AppState.addEventListener('change', this.onAppStateChange_);
const sharedData = await ShareExtension.data();
if (sharedData) {
reg.logger().info('Received shared data');
if (this.props.selectedFolderId) {
handleShared(sharedData, this.props.selectedFolderId, this.props.dispatch);
} else {
reg.logger.info('Cannot handle share - default folder id is not set');
}
}
}
componentWillUnmount() {
AppState.removeEventListener('change', this.onAppStateChange_);
}
async componentDidUpdate(prevProps) {
componentDidUpdate(prevProps) {
if (this.props.showSideMenu !== prevProps.showSideMenu) {
Animated.timing(this.state.sideMenuContentOpacity, {
toValue: this.props.showSideMenu ? 0.5 : 0,
@@ -715,19 +719,8 @@ class AppComponent extends React.Component {
});
}
renderStartupScreen() {
return (
<View style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}>
<View style={{ alignItems: 'center' }}>
<Image style={{ marginBottom: 5 }} source={require('./images/StartUpIcon.png')} />
<Text style={{ color: '#444444' }}>{this.state.initMessage}</Text>
</View>
</View>
);
}
render() {
if (this.props.appState != 'ready') return this.renderStartupScreen();
if (this.props.appState != 'ready') return null;
const theme = themeStyle(this.props.themeId);
let sideMenuContent = null;

View File

@@ -281,29 +281,6 @@ const operations = [
iconWidth: 46,
iconHeight: 46,
},
// ============================================================================
// Mobile startup icon
// ============================================================================
{
source: 7,
dest: 'ReactNativeClient/images/StartUpIcon.png',
width: 64,
height: 64,
},
{
source: 7,
dest: 'ReactNativeClient/images/StartUpIcon@2x.png',
width: 128,
height: 128,
},
{
source: 7,
dest: 'ReactNativeClient/images/StartUpIcon@3x.png',
width: 192,
height: 192,
},
];
async function main() {

View File

@@ -3,7 +3,11 @@
{
"name": ".",
"path": "."
}
},
{
"name": "D:/Web/www/nextcloud/apps/joplin",
"path": "D:/Web/www/nextcloud/apps/joplin"
},
],
"settings": {
"files.exclude": {