diff --git a/src/prefs.nim b/src/prefs.nim index 825d407..8ae56ee 100644 --- a/src/prefs.nim +++ b/src/prefs.nim @@ -1,7 +1,8 @@ -import asyncdispatch, times, macros, tables, xmltree +import strutils import types +import prefs_impl -const hostname {.strdefine.} = "nitter.net" +export genUpdatePrefs withCustomDb("prefs.db", "", "", ""): try: @@ -9,74 +10,6 @@ withCustomDb("prefs.db", "", "", ""): except DbError: discard -type - PrefKind* = enum - checkbox, select, input - - Pref* = object - name*: string - label*: string - case kind*: PrefKind - of checkbox: - defaultState*: bool - of select: - defaultOption*: string - options*: seq[string] - of input: - defaultInput*: string - placeholder*: string - -# TODO: write DSL to simplify this -const prefList*: Table[string, seq[Pref]] = { - "Privacy": @[ - Pref(kind: input, name: "replaceTwitter", - label: "Replace Twitter links with Nitter (blank to disable)", - defaultInput: hostname, placeholder: "Nitter hostname"), - - Pref(kind: input, name: "replaceYouTube", - label: "Replace YouTube links with Invidious (blank to disable)", - defaultInput: "invidio.us", placeholder: "Invidious hostname") - ], - - "Media": @[ - Pref(kind: checkbox, name: "videoPlayback", - label: "Enable hls.js video playback (requires JavaScript)", - defaultState: false), - - Pref(kind: checkbox, name: "autoplayGifs", label: "Autoplay gifs", - defaultState: true) - ], - - "Display": @[ - Pref(kind: checkbox, name: "hideTweetStats", - label: "Hide tweet stats (replies, retweets, likes)", - defaultState: false), - - Pref(kind: checkbox, name: "hideBanner", label: "Hide profile banner", - defaultState: false), - - Pref(kind: checkbox, name: "stickyProfile", - label: "Make profile sidebar stick to top", - defaultState: true) - ] -}.toTable - -iterator allPrefs(): Pref = - for k, v in prefList: - for pref in v: - yield pref - -macro genDefaultPrefs*(): untyped = - result = nnkObjConstr.newTree(ident("Prefs")) - - for pref in allPrefs(): - result.add nnkExprColonExpr.newTree( - ident(pref.name), - case pref.kind - of checkbox: newLit(pref.defaultState) - of select: newLit(pref.defaultOption) - of input: newLit(pref.defaultInput)) - proc cache*(prefs: var Prefs) = withCustomDb("prefs.db", "", "", ""): try: @@ -101,25 +34,3 @@ proc resetPrefs*(prefs: var Prefs) = defPrefs.id = prefs.id cache(defPrefs) prefs = defPrefs - -macro genUpdatePrefs*(): untyped = - result = nnkStmtList.newTree() - - for pref in allPrefs(): - let ident = ident(pref.name) - let value = nnkPrefix.newTree(ident("@"), newLit(pref.name)) - - case pref.kind - of checkbox: - result.add quote do: prefs.`ident` = `value` == "on" - of input: - result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`)) - of select: - let options = pref.options - let default = pref.defaultOption - result.add quote do: - if `value` in `options`: prefs.`ident` = `value` - else: prefs.`ident` = `default` - - result.add quote do: - cache(prefs) diff --git a/src/prefs_impl.nim b/src/prefs_impl.nim new file mode 100644 index 0000000..53c37ee --- /dev/null +++ b/src/prefs_impl.nim @@ -0,0 +1,110 @@ +import macros, tables, strutils, xmltree + +const hostname {.strdefine.} = "nitter.net" + +type + PrefKind* = enum + checkbox, select, input + + Pref* = object + name*: string + label*: string + case kind*: PrefKind + of checkbox: + defaultState*: bool + of select: + defaultOption*: string + options*: seq[string] + of input: + defaultInput*: string + placeholder*: string + +# TODO: write DSL to simplify this +const prefList*: Table[string, seq[Pref]] = { + "Privacy": @[ + Pref(kind: input, name: "replaceTwitter", + label: "Replace Twitter links with Nitter (blank to disable)", + defaultInput: hostname, placeholder: "Nitter hostname"), + + Pref(kind: input, name: "replaceYouTube", + label: "Replace YouTube links with Invidious (blank to disable)", + defaultInput: "invidio.us", placeholder: "Invidious hostname") + ], + + "Media": @[ + Pref(kind: checkbox, name: "videoPlayback", + label: "Enable hls.js video playback (requires JavaScript)", + defaultState: false), + + Pref(kind: checkbox, name: "autoplayGifs", label: "Autoplay gifs", + defaultState: true) + ], + + "Display": @[ + Pref(kind: checkbox, name: "hideTweetStats", + label: "Hide tweet stats (replies, retweets, likes)", + defaultState: false), + + Pref(kind: checkbox, name: "hideBanner", label: "Hide profile banner", + defaultState: false), + + Pref(kind: checkbox, name: "stickyProfile", + label: "Make profile sidebar stick to top", + defaultState: true) + ] +}.toTable + +iterator allPrefs(): Pref = + for k, v in prefList: + for pref in v: + yield pref + +macro genDefaultPrefs*(): untyped = + result = nnkObjConstr.newTree(ident("Prefs")) + + for pref in allPrefs(): + let default = + case pref.kind + of checkbox: newLit(pref.defaultState) + of select: newLit(pref.defaultOption) + of input: newLit(pref.defaultInput) + + result.add nnkExprColonExpr.newTree(ident(pref.name), default) + +macro genUpdatePrefs*(): untyped = + result = nnkStmtList.newTree() + + for pref in allPrefs(): + let ident = ident(pref.name) + let value = nnkPrefix.newTree(ident("@"), newLit(pref.name)) + + case pref.kind + of checkbox: + result.add quote do: prefs.`ident` = `value` == "on" + of input: + result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`)) + of select: + let options = pref.options + let default = pref.defaultOption + result.add quote do: + if `value` in `options`: prefs.`ident` = `value` + else: prefs.`ident` = `default` + + result.add quote do: + cache(prefs) + +macro genPrefsType*(): untyped = + result = nnkTypeSection.newTree(nnkTypeDef.newTree( + nnkPostfix.newTree(ident("*"), ident("Prefs")), newEmptyNode(), + nnkObjectTy.newTree(newEmptyNode(), newEmptyNode(), nnkRecList.newTree()))) + + result[0][2][2].add nnkIdentDefs.newTree( + nnkPostfix.newTree(ident("*"), ident("id")), ident("int"), newEmptyNode()) + + for pref in allPrefs(): + result[0][2][2].add nnkIdentDefs.newTree( + nnkPostfix.newTree(ident("*"), ident(pref.name)), + (case pref.kind + of checkbox: ident("bool") + of input, select: ident("string")), + newEmptyNode()) diff --git a/src/types.nim b/src/types.nim index 2ad4f7b..7256b9b 100644 --- a/src/types.nim +++ b/src/types.nim @@ -1,5 +1,6 @@ import times, sequtils, options import norm/sqlite +import prefs_impl export sqlite, options @@ -49,14 +50,7 @@ db("cache.db", "", "", ""): formatIt: dbValue($it) .}: VideoType - Prefs* = object - videoPlayback*: bool - autoplayGifs*: bool - hideTweetStats*: bool - hideBanner*: bool - stickyProfile*: bool - replaceYouTube*: string - replaceTwitter*: string + genPrefsType() type QueryKind* = enum diff --git a/src/views/preferences.nim b/src/views/preferences.nim index 30c79d7..70a0a5b 100644 --- a/src/views/preferences.nim +++ b/src/views/preferences.nim @@ -1,7 +1,7 @@ import tables, macros, strformat, xmltree import karax/[karaxdsl, vdom, vstyles] -import ../types, ../prefs +import ../types, ../prefs_impl proc genCheckbox(pref, label: string; state: bool): VNode = buildHtml(tdiv(class="pref-group")):