Skip to content

Commit

Permalink
Merge pull request #266 from Totto16/fix-backslash-escape
Browse files Browse the repository at this point in the history
Fix Backslash Error
  • Loading branch information
Totto16 authored May 30, 2024
2 parents 082a835 + 3189974 commit 19f0d20
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 31 deletions.
19 changes: 17 additions & 2 deletions src/utils/compatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,24 @@ import GLib from '@girs/glib-2.0';
import { Notification, Source as MessageTraySource } from '@girs/gnome-shell/dist/ui/messageTray';
import St from '@girs/st-14';

// better typed functions for GDA

// we get / have to store strings for dates and numbers for boolean
type MapGDATypes<T> = T extends boolean ? number : T extends Date ? string : T;

//@ts-expect-error: this extends the types, to be more specific, but the generic types don't like that extensions
export interface DataModelIter<T> extends Gda5.DataModelIter {
get_value_for_field<K extends keyof T>(key: K): MapGDATypes<T[K]>;
}

//@ts-expect-error: this extends the types, to be more specific, but the generic types don't like that extensions
export interface SqlBuilder<T> extends Gda5.SqlBuilder {
add_field_value_as_gvalue<K extends keyof T>(key: K, value: MapGDATypes<T[K]>): void;
}

// compatibility functions for Gda 5.0 and 6.0

function isGda6Builder(builder: Gda5.SqlBuilder | Gda6.SqlBuilder): builder is Gda6.SqlBuilder {
function isGda6Builder(builder: Gda5.SqlBuilder | Gda6.SqlBuilder | SqlBuilder<any>): builder is Gda6.SqlBuilder {
return builder.add_expr_value.length === 1;
}

Expand All @@ -16,7 +31,7 @@ function isGda6Builder(builder: Gda5.SqlBuilder | Gda6.SqlBuilder): builder is G
* @param value any
* @returns expr id
*/
export function add_expr_value(builder: Gda5.SqlBuilder | Gda6.SqlBuilder, value: any): number {
export function add_expr_value(builder: Gda5.SqlBuilder | Gda6.SqlBuilder | SqlBuilder<any>, value: any): number {
if (isGda6Builder(builder)) {
return builder.add_expr_value(value);
}
Expand Down
61 changes: 32 additions & 29 deletions src/utils/db.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Gda5 from '@girs/gda-5.0';
import type { ExtensionBase } from '@girs/gnome-shell/dist/extensions/sharedInternals';
import { add_expr_value } from '@pano/utils/compatibility';
import { add_expr_value, type DataModelIter, type SqlBuilder } from '@pano/utils/compatibility';
import { getDbPath, logger } from '@pano/utils/shell';

const debug = logger('database');
Expand Down Expand Up @@ -214,20 +214,20 @@ class Database {

const builder = new Gda5.SqlBuilder({
stmt_type: Gda5.SqlStatementType.INSERT,
});
}) as SqlBuilder<DBItem>;

builder.set_table('clipboard');
//Note: casting required, since this is a gjs convention, that you don't have to pass a GObject.Value, this is needed for teh C API, but GJS constructs it on the fly
builder.add_field_value_as_gvalue('itemType', dbItem.itemType as any);
builder.add_field_value_as_gvalue('content', dbItem.content as any);
builder.add_field_value_as_gvalue('copyDate', dbItem.copyDate.toISOString() as any);
builder.add_field_value_as_gvalue('isFavorite', +dbItem.isFavorite as any);
builder.add_field_value_as_gvalue('matchValue', dbItem.matchValue as any);
builder.add_field_value_as_gvalue('itemType', dbItem.itemType);
builder.add_field_value_as_gvalue('content', dbItem.content);
builder.add_field_value_as_gvalue('copyDate', dbItem.copyDate.toISOString());
builder.add_field_value_as_gvalue('isFavorite', +dbItem.isFavorite);
builder.add_field_value_as_gvalue('matchValue', dbItem.matchValue);
if (dbItem.searchValue) {
builder.add_field_value_as_gvalue('searchValue', dbItem.searchValue as any);
builder.add_field_value_as_gvalue('searchValue', dbItem.searchValue);
}
if (dbItem.metaData) {
builder.add_field_value_as_gvalue('metaData', dbItem.metaData as any);
builder.add_field_value_as_gvalue('metaData', dbItem.metaData);
}
const [_, row] = this.connection.statement_execute_non_select(builder.get_statement(), null);
const id = row?.get_nth_holder(0).get_value() as any as number;
Expand All @@ -254,20 +254,20 @@ class Database {

const builder = new Gda5.SqlBuilder({
stmt_type: Gda5.SqlStatementType.UPDATE,
});
}) as SqlBuilder<DBItem>;

builder.set_table('clipboard');
//Note: casting required, since this is a gjs convention, that you don't have to pass a GObject.Value, this is needed for teh C API, but GJS constructs it on the fly
builder.add_field_value_as_gvalue('itemType', dbItem.itemType as any);
builder.add_field_value_as_gvalue('content', dbItem.content as any);
builder.add_field_value_as_gvalue('copyDate', dbItem.copyDate.toISOString() as any);
builder.add_field_value_as_gvalue('isFavorite', +dbItem.isFavorite as any);
builder.add_field_value_as_gvalue('matchValue', dbItem.matchValue as any);
builder.add_field_value_as_gvalue('itemType', dbItem.itemType);
builder.add_field_value_as_gvalue('content', dbItem.content);
builder.add_field_value_as_gvalue('copyDate', dbItem.copyDate.toISOString());
builder.add_field_value_as_gvalue('isFavorite', +dbItem.isFavorite);
builder.add_field_value_as_gvalue('matchValue', dbItem.matchValue);
if (dbItem.searchValue) {
builder.add_field_value_as_gvalue('searchValue', dbItem.searchValue as any);
builder.add_field_value_as_gvalue('searchValue', dbItem.searchValue);
}
if (dbItem.metaData) {
builder.add_field_value_as_gvalue('metaData', dbItem.metaData as any);
builder.add_field_value_as_gvalue('metaData', dbItem.metaData);
}
builder.set_where(
builder.add_cond(
Expand Down Expand Up @@ -313,28 +313,31 @@ class Database {

const dm = this.connection.statement_execute_select(clipboardQuery.statement, null);

const iter = dm.create_iter();
const iter = dm.create_iter() as DataModelIter<DBItem>;
const itemList: DBItem[] = [];

while (iter.move_next()) {
//Note: casting required, since this is a gjs convention, that any GObject.Value is just the value (e.g. string, number etc.) this types are from C, so there is no dynamic return value so they have to use GObject.Value
const id = iter.get_value_for_field('id') as any as number;
const itemType = iter.get_value_for_field('itemType') as any as ItemType;
const content = iter.get_value_for_field('content') as any as string;
const copyDate = iter.get_value_for_field('copyDate') as any as string;
const isFavorite = iter.get_value_for_field('isFavorite') as any as number;
const matchValue = iter.get_value_for_field('matchValue') as any as string;
const searchValue = iter.get_value_for_field('searchValue') as any as string;
const metaData = iter.get_value_for_field('metaData') as any as string;
const id = iter.get_value_for_field('id');
const itemType = iter.get_value_for_field('itemType');
const content = iter.get_value_for_field('content');
const contentUnescaped = Gda5.default_unescape_string(content) ?? content;
const copyDate = iter.get_value_for_field('copyDate');
const isFavorite = iter.get_value_for_field('isFavorite');
const matchValue = iter.get_value_for_field('matchValue');
const matchValueUnescaped = Gda5.default_unescape_string(matchValue) ?? matchValue;
const searchValue = iter.get_value_for_field('searchValue');
const searchValueUnescaped = searchValue ? Gda5.default_unescape_string(searchValue) ?? searchValue : undefined;
const metaData = iter.get_value_for_field('metaData');

itemList.push({
id,
itemType,
content,
content: contentUnescaped,
copyDate: new Date(copyDate),
isFavorite: !!isFavorite,
matchValue,
searchValue,
matchValue: matchValueUnescaped,
searchValue: searchValueUnescaped,
metaData,
});
}
Expand Down

0 comments on commit 19f0d20

Please sign in to comment.