prefs.nim 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import asyncdispatch, times, macros, tables, xmltree
  2. import types
  3. const hostname {.strdefine.} = "nitter.net"
  4. withCustomDb("prefs.db", "", "", ""):
  5. try:
  6. createTables()
  7. except DbError:
  8. discard
  9. type
  10. PrefKind* = enum
  11. checkbox, select, input
  12. Pref* = object
  13. name*: string
  14. label*: string
  15. case kind*: PrefKind
  16. of checkbox:
  17. defaultState*: bool
  18. of select:
  19. defaultOption*: string
  20. options*: seq[string]
  21. of input:
  22. defaultInput*: string
  23. placeholder*: string
  24. # TODO: write DSL to simplify this
  25. const prefList*: Table[string, seq[Pref]] = {
  26. "Privacy": @[
  27. Pref(kind: input, name: "replaceTwitter",
  28. label: "Replace Twitter links with Nitter (blank to disable)",
  29. defaultInput: hostname, placeholder: "Nitter hostname"),
  30. Pref(kind: input, name: "replaceYouTube",
  31. label: "Replace YouTube links with Invidious (blank to disable)",
  32. defaultInput: "invidio.us", placeholder: "Invidious hostname")
  33. ],
  34. "Media": @[
  35. Pref(kind: checkbox, name: "videoPlayback",
  36. label: "Enable hls.js video playback (requires JavaScript)",
  37. defaultState: false),
  38. Pref(kind: checkbox, name: "autoplayGifs", label: "Autoplay gifs",
  39. defaultState: true),
  40. ],
  41. "Display": @[
  42. Pref(kind: checkbox, name: "hideTweetStats",
  43. label: "Hide tweet stats (replies, retweets, likes)",
  44. defaultState: false),
  45. Pref(kind: checkbox, name: "hideBanner", label: "Hide profile banner",
  46. defaultState: false),
  47. Pref(kind: checkbox, name: "stickyProfile",
  48. label: "Make profile sidebar stick to top",
  49. defaultState: true)
  50. ]
  51. }.toTable
  52. iterator allPrefs(): Pref =
  53. for k, v in prefList:
  54. for pref in v:
  55. yield pref
  56. macro genDefaultPrefs*(): untyped =
  57. result = nnkObjConstr.newTree(ident("Prefs"))
  58. for pref in allPrefs():
  59. result.add nnkExprColonExpr.newTree(
  60. ident(pref.name),
  61. case pref.kind
  62. of checkbox: newLit(pref.defaultState)
  63. of select: newLit(pref.defaultOption)
  64. of input: newLit(pref.defaultInput))
  65. proc cache*(prefs: var Prefs) =
  66. withCustomDb("prefs.db", "", "", ""):
  67. try:
  68. doAssert prefs.id != 0
  69. discard Prefs.getOne("id = ?", prefs.id)
  70. prefs.update()
  71. except AssertionError, KeyError:
  72. prefs.insert()
  73. proc getPrefs*(id: string): Prefs =
  74. if id.len == 0: return genDefaultPrefs()
  75. withCustomDb("prefs.db", "", "", ""):
  76. try:
  77. result.getOne("id = ?", id)
  78. except KeyError:
  79. result = genDefaultPrefs()
  80. cache(result)
  81. macro genUpdatePrefs*(): untyped =
  82. result = nnkStmtList.newTree()
  83. for pref in allPrefs():
  84. let ident = ident(pref.name)
  85. let value = nnkPrefix.newTree(ident("@"), newLit(pref.name))
  86. case pref.kind
  87. of checkbox:
  88. result.add quote do: prefs.`ident` = `value` == "on"
  89. of input:
  90. result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`))
  91. of select:
  92. let options = pref.options
  93. let default = pref.defaultOption
  94. result.add quote do:
  95. if `value` in `options`: prefs.`ident` = `value`
  96. else: prefs.`ident` = `default`
  97. result.add quote do:
  98. cache(prefs)