mirror of
https://github.com/laurent22/joplin.git
synced 2025-02-04 19:16:07 +02:00
Co-authored-by: Georg Grab <talkdirty@users.noreply.github.com>
This commit is contained in:
parent
6d56bb8afd
commit
6b8e84332d
@ -622,7 +622,7 @@ class Application extends BaseApplication {
|
|||||||
|
|
||||||
// the following menu items will be available for all OS under Tools
|
// the following menu items will be available for all OS under Tools
|
||||||
const toolsItemsAll = [{
|
const toolsItemsAll = [{
|
||||||
label: _('Resources'),
|
label: _('Note attachments...'),
|
||||||
click: () => {
|
click: () => {
|
||||||
this.dispatch({
|
this.dispatch({
|
||||||
type: 'NAV_GO',
|
type: 'NAV_GO',
|
||||||
|
@ -267,6 +267,7 @@ class HeaderComponent extends React.Component {
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
cursor: 'default',
|
cursor: 'default',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
|
userSelect: 'none',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (showBackButton) {
|
if (showBackButton) {
|
||||||
|
@ -8,9 +8,14 @@ const { Header } = require('./Header.min.js');
|
|||||||
const prettyBytes = require('pretty-bytes');
|
const prettyBytes = require('pretty-bytes');
|
||||||
const Resource = require('lib/models/Resource.js');
|
const Resource = require('lib/models/Resource.js');
|
||||||
|
|
||||||
|
interface Style {
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
style: any;
|
|
||||||
theme: any;
|
theme: any;
|
||||||
|
style: Style
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Resource {
|
interface Resource {
|
||||||
@ -32,6 +37,8 @@ interface ResourceTable {
|
|||||||
onResourceClick: (resource: Resource) => any
|
onResourceClick: (resource: Resource) => any
|
||||||
onResourceDelete: (resource: Resource) => any
|
onResourceDelete: (resource: Resource) => any
|
||||||
onToggleSorting: (order: SortingOrder) => any
|
onToggleSorting: (order: SortingOrder) => any
|
||||||
|
theme: any
|
||||||
|
style: Style
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortingOrder = 'size' | 'name'
|
type SortingOrder = 'size' | 'name'
|
||||||
@ -45,29 +52,58 @@ interface ActiveSorting {
|
|||||||
const ResourceTable: React.FC<ResourceTable> = (props: ResourceTable) => {
|
const ResourceTable: React.FC<ResourceTable> = (props: ResourceTable) => {
|
||||||
const sortOrderEngagedMarker = (s: SortingOrder) => {
|
const sortOrderEngagedMarker = (s: SortingOrder) => {
|
||||||
return (
|
return (
|
||||||
<a href="#" onClick={ () => props.onToggleSorting(s) }>{
|
<a href="#"
|
||||||
(props.sorting.order === s && props.sorting.type === 'desc') ? '▾' : '▴' }</a>
|
style={{ color: props.theme.htmlLinkColor }}
|
||||||
|
onClick={() => props.onToggleSorting(s)}>{
|
||||||
|
(props.sorting.order === s && props.sorting.type === 'desc') ? '▾' : '▴'}</a>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return <table style={{ width: '90%' }}>
|
|
||||||
|
const titleCellStyle = {
|
||||||
|
...props.theme.textStyle,
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
maxWidth: 1,
|
||||||
|
width: '100%',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
};
|
||||||
|
|
||||||
|
const cellStyle = {
|
||||||
|
...props.theme.textStyleMinor,
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
width: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerStyle = {
|
||||||
|
...props.theme.textStyle,
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
width: 1,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
};
|
||||||
|
|
||||||
|
return <table style={{ width: '100%' }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{_('Title')} { sortOrderEngagedMarker('name') }</th>
|
<th style={headerStyle}>{_('Title')} {sortOrderEngagedMarker('name')}</th>
|
||||||
<th>{_('Size')} { sortOrderEngagedMarker('size') }</th>
|
<th style={headerStyle}>{_('Size')} {sortOrderEngagedMarker('size')}</th>
|
||||||
<th>{_('ID')}</th>
|
<th style={headerStyle}>{_('ID')}</th>
|
||||||
<th>{_('Action')}</th>
|
<th style={headerStyle}>{_('Action')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{props.resources.map((resource: Resource, index: number) =>
|
{props.resources.map((resource: Resource, index: number) =>
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td>
|
<td style={titleCellStyle} className="titleCell">
|
||||||
<a href="#" onClick={() => props.onResourceClick(resource)}>{resource.title}</a>
|
<a
|
||||||
|
style={{ color: props.theme.htmlLinkColor }}
|
||||||
|
href="#"
|
||||||
|
onClick={() => props.onResourceClick(resource)}>{resource.title || `(${_('Untitled')})`}
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{prettyBytes(resource.size)}</td>
|
<td style={cellStyle} className="dataCell">{prettyBytes(resource.size)}</td>
|
||||||
<td>{resource.id}</td>
|
<td style={cellStyle} className="dataCell">{resource.id}</td>
|
||||||
<td>
|
<td style={cellStyle} className="dataCell">
|
||||||
<button onClick={ () => props.onResourceDelete(resource) }>{_('Delete')}</button>
|
<button style={props.theme.buttonStyle} onClick={() => props.onResourceDelete(resource)}>{_('Delete')}</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
@ -123,6 +159,13 @@ class ResourceScreenComponent extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onResourceDelete(resource: Resource) {
|
onResourceDelete(resource: Resource) {
|
||||||
|
const ok = bridge().showConfirmMessageBox(_('Delete attachment "%s"?', resource.title), {
|
||||||
|
buttons: [_('Delete'), _('Cancel')],
|
||||||
|
defaultId: 1,
|
||||||
|
});
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Resource.delete(resource.id)
|
Resource.delete(resource.id)
|
||||||
.catch((error: Error) => {
|
.catch((error: Error) => {
|
||||||
bridge().showErrorMessageBox(error.message);
|
bridge().showErrorMessageBox(error.message);
|
||||||
@ -158,9 +201,23 @@ class ResourceScreenComponent extends React.Component<Props, State> {
|
|||||||
const style = this.props.style;
|
const style = this.props.style;
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
|
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
|
||||||
return <div>
|
|
||||||
|
const rootStyle = {
|
||||||
|
...style,
|
||||||
|
overflowY: 'scroll',
|
||||||
|
color: theme.color,
|
||||||
|
padding: 20,
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
};
|
||||||
|
rootStyle.height = style.height - 35; // Minus the header height
|
||||||
|
delete rootStyle.width;
|
||||||
|
|
||||||
|
return <div style={{ ...theme.containerStyle, fontFamily: theme.fontFamily }}>
|
||||||
<Header style={headerStyle} />
|
<Header style={headerStyle} />
|
||||||
<div style={{ ...style, margin: '20px', overflow: 'scroll' }}>
|
<div style={rootStyle}>
|
||||||
|
<div style={{ ...theme.notificationBox, marginBottom: 10 }}>{
|
||||||
|
_('This is an advanced tool to show the attachments that are linked to your notes. Please be careful when deleting one of them as they cannot be restored afterwards.')
|
||||||
|
}</div>
|
||||||
{this.state.isLoading && <div>{_('Please wait...')}</div>}
|
{this.state.isLoading && <div>{_('Please wait...')}</div>}
|
||||||
{!this.state.isLoading && <div>
|
{!this.state.isLoading && <div>
|
||||||
{!this.state.resources && <div>
|
{!this.state.resources && <div>
|
||||||
@ -171,11 +228,13 @@ class ResourceScreenComponent extends React.Component<Props, State> {
|
|||||||
<div>{_('Warning: not all resources shown for performance reasons (limit: %s).', MAX_RESOURCES)}</div>
|
<div>{_('Warning: not all resources shown for performance reasons (limit: %s).', MAX_RESOURCES)}</div>
|
||||||
}
|
}
|
||||||
{this.state.resources && <ResourceTable
|
{this.state.resources && <ResourceTable
|
||||||
resources={ this.state.resources }
|
theme={theme}
|
||||||
sorting={ this.state.sorting }
|
style={style}
|
||||||
onToggleSorting={ (order) => this.onToggleSortOrder(order) }
|
resources={this.state.resources}
|
||||||
onResourceClick={ (resource) => this.openResource(resource) }
|
sorting={this.state.sorting}
|
||||||
onResourceDelete={ (resource) => this.onResourceDelete(resource) }
|
onToggleSorting={(order) => this.onToggleSortOrder(order)}
|
||||||
|
onResourceClick={(resource) => this.openResource(resource)}
|
||||||
|
onResourceDelete={(resource) => this.onResourceDelete(resource)}
|
||||||
/>}
|
/>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ class RootComponent extends React.Component {
|
|||||||
DropboxLogin: { screen: DropboxLoginScreen, title: () => _('Dropbox Login') },
|
DropboxLogin: { screen: DropboxLoginScreen, title: () => _('Dropbox Login') },
|
||||||
Import: { screen: ImportScreen, title: () => _('Import') },
|
Import: { screen: ImportScreen, title: () => _('Import') },
|
||||||
Config: { screen: ConfigScreen, title: () => _('Options') },
|
Config: { screen: ConfigScreen, title: () => _('Options') },
|
||||||
Resources: { screen: ResourceScreen, title: () => _('Resources') },
|
Resources: { screen: ResourceScreen, title: () => _('Note attachments') },
|
||||||
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },
|
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,6 +131,7 @@ class SideBarComponent extends React.Component {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
userSelect: 'none',
|
||||||
},
|
},
|
||||||
listItemSelected: {
|
listItemSelected: {
|
||||||
backgroundColor: theme.selectedColor2,
|
backgroundColor: theme.selectedColor2,
|
||||||
@ -160,6 +161,7 @@ class SideBarComponent extends React.Component {
|
|||||||
paddingLeft: 8,
|
paddingLeft: 8,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
userSelect: 'none',
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
padding: 6,
|
padding: 6,
|
||||||
@ -176,6 +178,7 @@ class SideBarComponent extends React.Component {
|
|||||||
marginLeft: 5,
|
marginLeft: 5,
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
cursor: 'default',
|
cursor: 'default',
|
||||||
|
userSelect: 'none',
|
||||||
},
|
},
|
||||||
syncReport: {
|
syncReport: {
|
||||||
fontFamily: theme.fontFamily,
|
fontFamily: theme.fontFamily,
|
||||||
@ -195,6 +198,7 @@ class SideBarComponent extends React.Component {
|
|||||||
noteCount: {
|
noteCount: {
|
||||||
paddingLeft: 5,
|
paddingLeft: 5,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
|
userSelect: 'none',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ const style = createSelector(
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: 9,
|
padding: 9,
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
|
userSelect: 'none',
|
||||||
},
|
},
|
||||||
buttonIcon: {
|
buttonIcon: {
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
|
@ -5,7 +5,7 @@ const darkStyle = {
|
|||||||
color: '#dddddd',
|
color: '#dddddd',
|
||||||
colorError: 'red',
|
colorError: 'red',
|
||||||
colorWarn: '#9A5B00',
|
colorWarn: '#9A5B00',
|
||||||
colorFaded: '#777777', // For less important text
|
colorFaded: '#999999', // For less important text
|
||||||
colorBright: '#ffffff', // For important text
|
colorBright: '#ffffff', // For important text
|
||||||
dividerColor: '#555555',
|
dividerColor: '#555555',
|
||||||
selectedColor: '#333333',
|
selectedColor: '#333333',
|
||||||
|
@ -201,6 +201,14 @@ function addExtraStyles(style) {
|
|||||||
marginRight: 6,
|
marginRight: 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
style.notificationBox = {
|
||||||
|
backgroundColor: style.warningBackgroundColor,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 10,
|
||||||
|
fontSize: style.fontSize,
|
||||||
|
};
|
||||||
|
|
||||||
style.dialogTitle = Object.assign({}, style.h1Style, { marginBottom: '1.2em' });
|
style.dialogTitle = Object.assign({}, style.h1Style, { marginBottom: '1.2em' });
|
||||||
|
|
||||||
style.dropdownList = Object.assign({}, style.inputStyle);
|
style.dropdownList = Object.assign({}, style.inputStyle);
|
||||||
@ -299,6 +307,7 @@ function themeStyle(theme) {
|
|||||||
color: output.color,
|
color: output.color,
|
||||||
backgroundColor: output.backgroundColor,
|
backgroundColor: output.backgroundColor,
|
||||||
borderColor: output.dividerColor,
|
borderColor: output.dividerColor,
|
||||||
|
userSelect: 'none',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user