Skip to content

Commit

Permalink
Desktop, Mobile: Add Joplin Cloud account information to configuratio…
Browse files Browse the repository at this point in the history
…n screen (#10553)
  • Loading branch information
pedr committed Jun 12, 2024
1 parent 7d0cc67 commit 889c395
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 30 deletions.
4 changes: 3 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
packages/app-mobile/components/screens/ConfigScreen/FileSystemPathSelector.js
packages/app-mobile/components/screens/ConfigScreen/JoplinCloudConfig.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportDebugReportButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportProfileButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
Expand Down Expand Up @@ -1243,7 +1244,8 @@ packages/lib/utils/ipc/utils/mergeCallbacksAndSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.test.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializableArray.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/joplinCloud/index.js
packages/lib/utils/joplinCloud/types.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
packages/app-mobile/components/screens/ConfigScreen/FileSystemPathSelector.js
packages/app-mobile/components/screens/ConfigScreen/JoplinCloudConfig.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportDebugReportButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportProfileButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
Expand Down Expand Up @@ -1222,7 +1223,8 @@ packages/lib/utils/ipc/utils/mergeCallbacksAndSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.test.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializableArray.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/joplinCloud/index.js
packages/lib/utils/joplinCloud/types.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
Expand Down
21 changes: 21 additions & 0 deletions packages/app-desktop/gui/JoplinCloudConfigScreen.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,25 @@
p {
padding: calc(var(--joplin-font-size) * 0.8);
}
}

.joplin-cloud-account-information {
margin-bottom: var(--joplin-margin);

table {
margin-bottom: var(--joplin-margin);
border: none;

td {
border: none;
border-bottom: 1px solid var(--joplin-border-color4);
padding: var(--joplin-font-size);
}

tr:last-child {
td {
border: none;
}
}
}
}
27 changes: 27 additions & 0 deletions packages/app-desktop/gui/JoplinCloudConfigScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { _ } from '@joplin/lib/locale';
import { clipboard } from 'electron';
import Button from './Button/Button';
import { Fragment } from 'react';
import { accountTypeToString } from '@joplin/lib/utils/joplinCloud/types';
import bridge from '../services/bridge';

type JoplinCloudConfigScreenProps = {
inboxEmail: string;
joplinCloudAccountType: number;
userEmail: string;
joplinCloudWebsite: string;
};

const JoplinCloudConfigScreen = (props: JoplinCloudConfigScreenProps) => {
Expand All @@ -17,8 +21,29 @@ const JoplinCloudConfigScreen = (props: JoplinCloudConfigScreenProps) => {

const isEmailToNoteAvailableInAccount = props.joplinCloudAccountType !== 1;

const goToJoplinCloudProfile = async () => {
await bridge().openExternal(`${props.joplinCloudWebsite}/users/me`);
};

return (
<div>
<div className="joplin-cloud-account-information">
<h2>{_('Account information')}</h2>
<table>
<tbody>
<tr>
<td><strong>{_('Account type')}</strong></td>
<td>{accountTypeToString(props.joplinCloudAccountType)}</td>
</tr>
<tr>
<td><strong>{_('Email')}</strong></td>
<td>{props.userEmail}</td>
</tr>
</tbody>
</table>
<Button onClick={goToJoplinCloudProfile} title={_('Go to Joplin Cloud profile')}/>
</div>

<h2>{_('Email to note')}</h2>
<p>{_('Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook')}</p>
{
Expand All @@ -38,6 +63,8 @@ const mapStateToProps = (state: AppState) => {
return {
inboxEmail: state.settings['sync.10.inboxEmail'],
joplinCloudAccountType: state.settings['sync.10.accountType'],
userEmail: state.settings['sync.10.userEmail'],
joplinCloudWebsite: state.settings['sync.10.website'],
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import NoteImportButton, { importButtonDefaultTitle, importButtonDescription } f
import SectionDescription from './SectionDescription';
import EnablePluginSupportPage from './plugins/EnablePluginSupportPage';
import getVersionInfoText from '../../../utils/getVersionInfoText';
import JoplinCloudConfig, { emailToNoteDescription, emailToNoteLabel } from './JoplinCloudConfig';

interface ConfigScreenState {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
Expand Down Expand Up @@ -538,33 +539,16 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
}

if (section.name === 'joplinCloud') {
const label = _('Email to note');
const description = _('Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook');
const isEmailToNoteAvailableInAccount = this.props.settings['sync.10.accountType'] !== 1;
const inboxEmailValue = isEmailToNoteAvailableInAccount ? this.props.settings['sync.10.inboxEmail'] : '-';
addSettingComponent(
<View key="joplinCloud">
<View style={this.styles().styleSheet.settingContainerNoBottomBorder}>
<Text style={this.styles().styleSheet.settingText}>{label}</Text>
<Text style={this.styles().styleSheet.settingTextEmphasis}>{inboxEmailValue}</Text>
</View>
{
!isEmailToNoteAvailableInAccount && (
<View style={this.styles().styleSheet.settingContainerNoBottomBorder}>
<Text style={this.styles().styleSheet.descriptionAlert}>{_('Your account doesn\'t have access to this feature')}</Text>
</View>
)
}
{
this.renderButton(
'sync.10.inboxEmail',
_('Copy to clipboard'),
() => isEmailToNoteAvailableInAccount && Clipboard.setString(this.props.settings['sync.10.inboxEmail']),
{ description, disabled: !isEmailToNoteAvailableInAccount },
)
}
</View>,
[label, description],
<JoplinCloudConfig
key="joplin-cloud-config"
accountType={this.props.settings['sync.10.accountType']}
inboxEmail={this.props.settings['sync.10.inboxEmail']}
userEmail={this.props.settings['sync.10.userEmail']}
website={this.props.settings['sync.10.website']}
styles={this.styles()}
/>,
[emailToNoteDescription(), emailToNoteLabel()],
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { _ } from '@joplin/lib/locale';
import * as React from 'react';
import { useCallback } from 'react';
import { View, Text, Linking } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import SettingsButton from './SettingsButton';
import { accountTypeToString } from '@joplin/lib/utils/joplinCloud/types';
import { LinkButton } from '../../buttons';
import { ConfigScreenStyles } from './configScreenStyles';
import { Divider } from 'react-native-paper';
import Logger from '@joplin/utils/Logger';

const logger = Logger.create('JoplinCloudConfig');

type JoplinCloudConfigProps = {
styles: ConfigScreenStyles;
accountType: string;
inboxEmail: string;
website: string;
userEmail: string;
};

export const emailToNoteLabel = () => _('Email to note');
export const emailToNoteDescription = () => _('Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook');

const JoplinCloudConfig = (props: JoplinCloudConfigProps) => {

const isEmailToNoteAvailableInAccount = props.accountType !== '1';
const inboxEmailValue = props.inboxEmail ?? '-';

const goToJoplinCloudProfile = useCallback(async () => {
await Linking.openURL(`${props.website}/users/me`);
}, [props.website]);

const accountTypeName = () => {
try {
if (!props.accountType) return 'Unknown';
return accountTypeToString(parseInt(props.accountType, 10));
} catch (error) {
logger.error(error);
return 'Unknown';
}
};

return (
<View>
<View style={props.styles.styleSheet.settingContainerNoBottomBorder}>
<Text style={props.styles.styleSheet.settingTextEmphasis}>{_('Account information')}</Text>
</View>
<View style={props.styles.styleSheet.settingContainerNoBottomBorder}>
<Text style={props.styles.styleSheet.settingText}>{_('Account type')}</Text>
<Text style={props.styles.styleSheet.settingTextEmphasis}>{accountTypeName()}</Text>
</View>
<View style={props.styles.styleSheet.settingContainerNoBottomBorder}>
<Text style={props.styles.styleSheet.settingText}>{_('Email')}</Text>
<Text selectable style={props.styles.styleSheet.settingTextEmphasis}>{props.userEmail}</Text>
</View>
<LinkButton onPress={goToJoplinCloudProfile}>
{_('Go to Joplin Cloud profile')}
</LinkButton>
<Divider bold />

<View style={props.styles.styleSheet.settingContainerNoBottomBorder}>
<Text style={props.styles.styleSheet.settingText}>{emailToNoteLabel()}</Text>
<Text style={props.styles.styleSheet.settingTextEmphasis}>{inboxEmailValue}</Text>
</View>
{
!isEmailToNoteAvailableInAccount && (
<View style={props.styles.styleSheet.settingContainerNoBottomBorder}>
<Text style={props.styles.styleSheet.descriptionAlert}>{_('Your account doesn\'t have access to this feature')}</Text>
</View>
)
}
<SettingsButton
title={_('Copy to clipboard')}
clickHandler={() => isEmailToNoteAvailableInAccount && Clipboard.setString(props.inboxEmail)}
description={emailToNoteDescription()}
statusComponent={undefined}
styles={props.styles}
disabled={!isEmailToNoteAvailableInAccount}
/>
</View>
);

};

export default JoplinCloudConfig;
2 changes: 2 additions & 0 deletions packages/lib/models/Setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,8 @@ class Setting extends BaseModel {

'sync.10.accountType': { value: 0, type: SettingItemType.Int, public: false },

'sync.10.userEmail': { value: '', type: SettingItemType.String, public: false },

'sync.5.syncTargets': { value: {}, type: SettingItemType.Object, public: false },

'sync.resourceDownloadMode': {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from 'fs-extra';
import markdownUtils, { MarkdownTableHeader, MarkdownTableRow } from '../markdownUtils';
import { _ } from '../locale';
import markdownUtils, { MarkdownTableHeader, MarkdownTableRow } from '../../markdownUtils';
import { _ } from '../../locale';
import { htmlentities } from '@joplin/utils/html';

type FeatureId = string;
Expand Down
16 changes: 16 additions & 0 deletions packages/lib/utils/joplinCloud/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
enum AccountType {
Default = 0,
Basic = 1,
Pro = 2,
Team = 3,
}

// eslint-disable-next-line import/prefer-default-export
export function accountTypeToString(accountType: AccountType): string {
if (accountType === AccountType.Default) return 'Default';
if (accountType === AccountType.Basic) return 'Basic';
if (accountType === AccountType.Pro) return 'Pro';
if (accountType === AccountType.Team) return 'Team';
const exhaustivenessCheck: never = accountType;
throw new Error(`Invalid type: ${exhaustivenessCheck}`);
}
2 changes: 2 additions & 0 deletions packages/lib/utils/userFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface UserApiResponse {
inbox_email?: string;
can_use_share_permissions?: number;
account_type?: number;
email: string;
}

const userFetcher = async () => {
Expand Down Expand Up @@ -40,6 +41,7 @@ const userFetcher = async () => {
Setting.setValue('sync.10.inboxEmail', owner.inbox_email ? owner.inbox_email : '');
Setting.setValue('sync.10.canUseSharePermissions', !!owner.can_use_share_permissions);
Setting.setValue('sync.10.accountType', owner.account_type);
Setting.setValue('sync.10.userEmail', owner.email);
};

// Listen to the event only once
Expand Down

0 comments on commit 889c395

Please sign in to comment.