Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Multi-select connections in Welcome window (Cmd+Click, Shift+Click) with bulk delete (⌘⌫), Move to Group, and multi-connect
- Drag-and-drop connections between groups, reorder within groups, and reorder groups
- Reorder connections within groups and reorder groups in Welcome window
- ClickHouse, MSSQL, Redis, XLSX Export, MQL Export, and SQL Import now ship as built-in plugins
- Large document safety caps for syntax highlighting (skip >5MB, throttle >50KB)
- Lazy-load full values for LONGTEXT/MEDIUMTEXT/CLOB columns in the detail pane sidebar
Expand Down
60 changes: 30 additions & 30 deletions TablePro.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
5A862000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A862000D00000000 /* SQLiteDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A862000100000000 /* SQLiteDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A863000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A863000D00000000 /* ClickHouseDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A863000100000000 /* ClickHouseDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A864000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A864000D00000000 /* MSSQLDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A864000100000000 /* MSSQLDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A865000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A865000D00000000 /* MySQLDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A865000100000000 /* MySQLDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A866000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A867000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A867000D00000000 /* RedisDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A867000100000000 /* RedisDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A868000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A868000D00000000 /* PostgreSQLDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A868000100000000 /* PostgreSQLDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A869000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
Expand All @@ -26,15 +29,12 @@
5A86B000D00000000 /* JSONExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86B000100000000 /* JSONExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86C000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A86C000D00000000 /* SQLExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86C000100000000 /* SQLExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A863000D00000000 /* ClickHouseDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A863000100000000 /* ClickHouseDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A864000D00000000 /* MSSQLDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A864000100000000 /* MSSQLDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A867000D00000000 /* RedisDriver.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A867000100000000 /* RedisDriver.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86D000D00000000 /* XLSXExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86D000100000000 /* XLSXExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86E000D00000000 /* MQLExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86E000100000000 /* MQLExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86F000D00000000 /* SQLImport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86F000100000000 /* SQLImport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86D000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A86D000D00000000 /* XLSXExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86D000100000000 /* XLSXExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86E000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A86E000D00000000 /* MQLExport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86E000100000000 /* MQLExport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A86F000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5A86F000D00000000 /* SQLImport.tableplugin in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = 5A86F000100000000 /* SQLImport.tableplugin */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
5A87A000A00000000 /* TableProPluginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A860000100000000 /* TableProPluginKit.framework */; };
5ACE00012F4F000000000004 /* CodeEditSourceEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 5ACE00012F4F000000000002 /* CodeEditSourceEditor */; };
5ACE00012F4F000000000005 /* CodeEditLanguages in Frameworks */ = {isa = PBXBuildFile; productRef = 5ACE00012F4F000000000003 /* CodeEditLanguages */; };
Expand Down Expand Up @@ -90,13 +90,27 @@
remoteGlobalIDString = 5A863000000000000;
remoteInfo = ClickHouseDriver;
};
5A864000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A864000000000000;
remoteInfo = MSSQLDriver;
};
5A865000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A865000000000000;
remoteInfo = MySQLDriver;
};
5A867000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A867000000000000;
remoteInfo = RedisDriver;
};
5A868000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
Expand Down Expand Up @@ -132,20 +146,6 @@
remoteGlobalIDString = 5A86C000000000000;
remoteInfo = SQLExport;
};
5A864000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A864000000000000;
remoteInfo = MSSQLDriver;
};
5A867000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5A867000000000000;
remoteInfo = RedisDriver;
};
5A86D000B00000000 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5A1091BF2EF17EDC0055EA7C /* Project object */;
Expand Down Expand Up @@ -1793,11 +1793,21 @@
target = 5A863000000000000 /* ClickHouseDriver */;
targetProxy = 5A863000B00000000 /* PBXContainerItemProxy */;
};
5A864000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A864000000000000 /* MSSQLDriver */;
targetProxy = 5A864000B00000000 /* PBXContainerItemProxy */;
};
5A865000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A865000000000000 /* MySQLDriver */;
targetProxy = 5A865000B00000000 /* PBXContainerItemProxy */;
};
5A867000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A867000000000000 /* RedisDriver */;
targetProxy = 5A867000B00000000 /* PBXContainerItemProxy */;
};
5A868000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A868000000000000 /* PostgreSQLDriver */;
Expand All @@ -1823,16 +1833,6 @@
target = 5A86C000000000000 /* SQLExport */;
targetProxy = 5A86C000B00000000 /* PBXContainerItemProxy */;
};
5A864000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A864000000000000 /* MSSQLDriver */;
targetProxy = 5A864000B00000000 /* PBXContainerItemProxy */;
};
5A867000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A867000000000000 /* RedisDriver */;
targetProxy = 5A867000B00000000 /* PBXContainerItemProxy */;
};
5A86D000C00000000 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5A86D000000000000 /* XLSXExport */;
Expand Down
19 changes: 19 additions & 0 deletions TablePro/Core/Storage/ConnectionStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ final class ConnectionStorage {
deleteAllPluginSecureFields(for: connection.id, fieldIds: secureFieldIds)
}

/// Batch-delete multiple connections and clean up their Keychain entries
func deleteConnections(_ connectionsToDelete: [DatabaseConnection]) {
for conn in connectionsToDelete {
SyncChangeTracker.shared.markDeleted(.connection, id: conn.id.uuidString)
}
let idsToDelete = Set(connectionsToDelete.map(\.id))
var all = loadConnections()
all.removeAll { idsToDelete.contains($0.id) }
saveConnections(all)
for conn in connectionsToDelete {
deletePassword(for: conn.id)
deleteSSHPassword(for: conn.id)
deleteKeyPassphrase(for: conn.id)
deleteTOTPSecret(for: conn.id)
let fields = Self.secureFieldIds(for: conn.type)
deleteAllPluginSecureFields(for: conn.id, fieldIds: fields)
}
}

/// Duplicate a connection with a new UUID and "(Copy)" suffix
/// Copies all passwords from source connection to the duplicate
func duplicateConnection(_ connection: DatabaseConnection) -> DatabaseConnection {
Expand Down
60 changes: 60 additions & 0 deletions TablePro/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
}
},
"(%@)" : {
"extractionState" : "stale",
"localizations" : {
"tr" : {
"stringUnit" : {
Expand Down Expand Up @@ -3919,6 +3920,9 @@
}
}
}
},
"Are you sure you want to delete %lld connections? This cannot be undone." : {

Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
"Are you sure you want to delete this connection? This cannot be undone." : {
"localizations" : {
Expand Down Expand Up @@ -6525,6 +6529,28 @@
}
}
},
"Connect %lld Connections" : {
"localizations" : {
"en" : {
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "Connect %lld Connection"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "Connect %lld Connections"
}
}
}
}
}
}
},
"Connect Anyway" : {
"localizations" : {
"tr" : {
Expand Down Expand Up @@ -9299,6 +9325,28 @@
}
}
},
"Delete %lld Connections" : {
"localizations" : {
"en" : {
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete %lld Connection"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete %lld Connections"
}
}
}
}
}
}
},
"Delete Check Constraint" : {
"extractionState" : "stale",
"localizations" : {
Expand Down Expand Up @@ -12270,6 +12318,9 @@
}
}
}
},
"Failed to load full value" : {

},
"Failed to load plugin registry" : {
"extractionState" : "stale",
Expand Down Expand Up @@ -17573,6 +17624,9 @@
}
}
}
},
"Move to Group" : {

},
"Move Up" : {
"extractionState" : "stale",
Expand Down Expand Up @@ -18113,6 +18167,9 @@
}
}
}
},
"New Group..." : {

},
"New Jump Host" : {
"localizations" : {
Expand Down Expand Up @@ -23568,6 +23625,9 @@
}
}
}
},
"Remove from Group" : {

},
"Remove license from this machine" : {
"localizations" : {
Expand Down
Loading
Loading