Compare commits

...
Author SHA1 Message Date
Laurent Cozic 435cb12389 iOS 13.7.2 2026-07-31 12:17:47 +02:00
Laurent Cozic fbe9cd2b9d Desktop: Improve rendering of Markdown editor table context menu 2026-07-31 12:16:44 +02:00
3 changed files with 105 additions and 30 deletions

No files matched your search

@@ -597,7 +597,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
CURRENT_PROJECT_VERSION = 160;
CURRENT_PROJECT_VERSION = 161;
DEVELOPMENT_TEAM = A9BXAFS6CT;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Joplin/Info.plist;
@@ -606,7 +606,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 13.7.1;
MARKETING_VERSION = 13.7.2;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -632,7 +632,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
CURRENT_PROJECT_VERSION = 160;
CURRENT_PROJECT_VERSION = 161;
DEVELOPMENT_TEAM = A9BXAFS6CT;
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@@ -640,7 +640,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 13.7.1;
MARKETING_VERSION = 13.7.2;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -670,7 +670,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
FORCE_BUNDLING = YES;
@@ -709,7 +709,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_USER_SCRIPT_SANDBOXING = YES;
FORCE_BUNDLING = YES;
@@ -910,7 +910,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 160;
CURRENT_PROJECT_VERSION = 161;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A9BXAFS6CT;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -921,7 +921,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 13.7.1;
MARKETING_VERSION = 13.7.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
@@ -953,7 +953,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 160;
CURRENT_PROJECT_VERSION = 161;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A9BXAFS6CT;
GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -964,7 +964,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 13.7.1;
MARKETING_VERSION = 13.7.2;
MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -696,21 +696,30 @@ class TableWidget extends WidgetType {
menu.style.left = `${e.clientX}px`;
menu.style.top = `${e.clientY}px`;
type MenuItem = { label: string; action: ()=> void; hlRow?: number; hlCol?: number };
const items: MenuItem[] = [
{ label: '+ Insert row above', action: () => { syncDirtyCells(); this.apply(view, addRow(table, r <= 0 ? -1 : r - 2)); } },
{ label: '+ Insert row below', action: () => { syncDirtyCells(); this.apply(view, addRow(table, r === 0 ? -1 : r - 1)); } },
{ label: '+ Insert column left', action: () => { syncDirtyCells(); this.apply(view, addColumn(table, c - 1)); } },
{ label: '+ Insert column right', action: () => { syncDirtyCells(); this.apply(view, addColumn(table, c)); } },
type MenuItem = { icon: string; label: string; action: ()=> void; hlRow?: number; hlCol?: number; danger?: boolean };
type MenuEntry = MenuItem | 'divider';
// Grouped into: insert, move, then delete, with dividers between.
const insertGroup: MenuItem[] = [
{ icon: '⤒', label: 'Insert row above', action: () => { syncDirtyCells(); this.apply(view, addRow(table, r <= 0 ? -1 : r - 2)); } },
{ icon: '⤓', label: 'Insert row below', action: () => { syncDirtyCells(); this.apply(view, addRow(table, r === 0 ? -1 : r - 1)); } },
{ icon: '⇤', label: 'Insert column left', action: () => { syncDirtyCells(); this.apply(view, addColumn(table, c - 1)); } },
{ icon: '⇥', label: 'Insert column right', action: () => { syncDirtyCells(); this.apply(view, addColumn(table, c)); } },
];
if (r > 1) items.push({ label: '↑ Move row up', action: () => { syncDirtyCells(); this.apply(view, swapRows(table, r - 1, r - 2)); }, hlRow: r });
if (r > 0 && r < numBodyRows) items.push({ label: '↓ Move row down', action: () => { syncDirtyCells(); this.apply(view, swapRows(table, r - 1, r)); }, hlRow: r });
if (c > 0) items.push({ label: '← Move column left', action: () => { syncDirtyCells(); this.apply(view, swapColumns(table, c, c - 1)); }, hlCol: c });
if (c < numCols - 1) items.push({ label: '→ Move column right', action: () => { syncDirtyCells(); this.apply(view, swapColumns(table, c, c + 1)); }, hlCol: c });
const moveGroup: MenuItem[] = [];
if (r > 1) moveGroup.push({ icon: '↑', label: 'Move row up', action: () => { syncDirtyCells(); this.apply(view, swapRows(table, r - 1, r - 2)); }, hlRow: r });
if (r > 0 && r < numBodyRows) moveGroup.push({ icon: '↓', label: 'Move row down', action: () => { syncDirtyCells(); this.apply(view, swapRows(table, r - 1, r)); }, hlRow: r });
if (c > 0) moveGroup.push({ icon: '←', label: 'Move column left', action: () => { syncDirtyCells(); this.apply(view, swapColumns(table, c, c - 1)); }, hlCol: c });
if (c < numCols - 1) moveGroup.push({ icon: '→', label: 'Move column right', action: () => { syncDirtyCells(); this.apply(view, swapColumns(table, c, c + 1)); }, hlCol: c });
const deleteGroup: MenuItem[] = [];
// Delete row: only for body rows (header row cannot be removed)
if (r > 0) {
items.push({
label: '✕ Delete row',
deleteGroup.push({
icon: '✕',
label: 'Delete row',
danger: true,
action: () => {
syncDirtyCells();
this.apply(view, deleteRow(table, r - 1));
@@ -719,8 +728,10 @@ class TableWidget extends WidgetType {
});
}
// Delete column: last column → delete entire table, otherwise delete that column
items.push({
label: '✕ Delete column',
deleteGroup.push({
icon: '✕',
label: 'Delete column',
danger: true,
action: () => {
syncDirtyCells();
if (numCols <= 1) {
@@ -732,13 +743,35 @@ class TableWidget extends WidgetType {
hlCol: c,
});
for (const item of items) {
const entries: MenuEntry[] = [];
for (const group of [insertGroup, moveGroup, deleteGroup]) {
if (!group.length) continue;
if (entries.length) entries.push('divider');
entries.push(...group);
}
for (const entry of entries) {
if (entry === 'divider') {
const sep = doc.createElement('div');
sep.classList.add('cm-tw-ctx-divider');
menu.appendChild(sep);
continue;
}
const div = doc.createElement('div');
div.textContent = item.label;
div.classList.add('cm-tw-ctx-item');
if (entry.danger) div.classList.add('cm-tw-ctx-danger');
const icon = doc.createElement('span');
icon.classList.add('cm-tw-ctx-icon');
icon.textContent = entry.icon;
const label = doc.createElement('span');
label.classList.add('cm-tw-ctx-label');
label.textContent = entry.label;
div.appendChild(icon);
div.appendChild(label);
div.onmouseenter = () => {
clearHighlight();
if (item.hlRow !== undefined) highlightRow(item.hlRow);
if (item.hlCol !== undefined) highlightCol(item.hlCol);
if (entry.hlRow !== undefined) highlightRow(entry.hlRow);
if (entry.hlCol !== undefined) highlightCol(entry.hlCol);
};
div.onmouseleave = () => clearHighlight();
div.onmousedown = (ev) => {
@@ -746,7 +779,7 @@ class TableWidget extends WidgetType {
ev.stopPropagation();
clearHighlight();
menu.remove();
item.action();
entry.action();
};
menu.appendChild(div);
}
@@ -958,14 +991,37 @@ const tableTheme = EditorView.theme({
minWidth: '190px',
padding: '4px 0',
fontSize: '13px',
'& > div': {
'& .cm-tw-ctx-item': {
display: 'flex',
alignItems: 'center',
gap: '10px',
padding: '6px 14px',
cursor: 'pointer',
whiteSpace: 'nowrap',
color: 'var(--joplin-color, #222)',
'&:hover': {
backgroundColor: 'var(--joplin-background-color-hover3, #f0f0f0)',
},
},
'& .cm-tw-ctx-icon': {
flex: '0 0 auto',
width: '16px',
textAlign: 'center',
fontSize: '14px',
lineHeight: '1',
opacity: '0.75',
},
'& .cm-tw-ctx-danger': {
color: 'var(--joplin-destructive-color, #d3392c)',
},
'& .cm-tw-ctx-danger:hover': {
backgroundColor: 'var(--joplin-background-color-hover3, #f0f0f0)',
},
'& .cm-tw-ctx-divider': {
height: '1px',
margin: '4px 0',
backgroundColor: 'var(--joplin-divider-color, #ddd)',
},
},
});
+19
View File
@@ -1,5 +1,24 @@
# Joplin iOS Changelog
## [ios-v13.7.2](https://github.com/laurent22/joplin/releases/tag/ios-v13.7.2) - 2026-07-28T13:07:01Z
- New: Add shadow to note actions menu (#16053 by [@personalizedrefrigerator](https://github.com/personalizedrefrigerator))
- Improved: Add note lock configuration section (#15963) (#15853 by [@keshav0479](https://github.com/keshav0479))
- Improved: Consider tags and smart filters when opening the last open location on app start (#16058 by [@mrjo118](https://github.com/mrjo118))
- Improved: Improve drag-to-dismiss behavior for drawer menus (#16055 by [@personalizedrefrigerator](https://github.com/personalizedrefrigerator))
- Improved: Note action menu: Vertically align icons (#15996 by [@personalizedrefrigerator](https://github.com/personalizedrefrigerator))
- Improved: Note actions menu: Decrease padding size (#15998 by [@personalizedrefrigerator](https://github.com/personalizedrefrigerator))
- Improved: Provide a clear message on what needs to be done when sync fails due to wrong version (#15837) (#15828 by [@Rygaa](https://github.com/Rygaa))
- Improved: Update Search screen (#15736 by [@Rygaa](https://github.com/Rygaa))
- Fixed: Add file extension validation to import actions (#15960) (#15915 by [@mrjo118](https://github.com/mrjo118))
- Fixed: Avoid reverting to the default editor state when the editor reloads the same note (#15986) (#15968 by [@mrjo118](https://github.com/mrjo118))
- Fixed: Fix WebDAV support for Koofr (#15983) (#15975 by [@mrjo118](https://github.com/mrjo118))
- Fixed: Fix auto navigate to latest notebook shortly after app start, when the selected notebook was previously deleted (#15950) (#15914 by [@mrjo118](https://github.com/mrjo118))
- Fixed: New note list design does not include the padding in the touch target to open notes (#15987) (#15972 by [@Rygaa](https://github.com/Rygaa))
- Fixed: New note list design does not look good in multi select mode (#15990) (#15973 by [@Rygaa](https://github.com/Rygaa))
- Fixed: Prevent update to note via the api from refreshing the editor if the change is for a different note (#15985) (#15968 by [@mrjo118](https://github.com/mrjo118))
- Fixed: Upgrade CodeMirror View to v6.43.6 (#16017) (#16009 by [@mrjo118](https://github.com/mrjo118))
## [ios-v13.7.1](https://github.com/laurent22/joplin/releases/tag/ios-v13.7.1) - 2026-07-13T19:31:23Z
- New: Add notebook sort options in config screen (#15203 by Self Not Found)