UserPreferenceService.vala 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using Invercargill;
  2. using Invercargill.DataStructures;
  3. using Invercargill.Expressions;
  4. using InvercargillSql;
  5. using InvercargillSql.Orm;
  6. using Inversion;
  7. using ClankerSaddle.Data;
  8. namespace ClankerSaddle.Services {
  9. /** The user_preferences key of the Spry theme slug ("" = core default). */
  10. public const string PREF_THEME = "theme";
  11. /** The user_preferences key of the colour mode (auto|light|dark). */
  12. public const string PREF_MODE = "mode";
  13. /** The default colour mode when no preference is stored. */
  14. public const string MODE_DEFAULT = "auto";
  15. /**
  16. * Per-user preferences (goal 41 task 2): the account settings'
  17. * key/value store behind the Spry theme picker. Reads go through
  18. * the ORM query API; writes are raw UPSERTs — the table's
  19. * composite primary key (user_id, key) defeats the ORM's
  20. * single-column update_async, so INSERT ... ON CONFLICT replaces
  21. * both halves of the pair.
  22. *
  23. * The theme helpers ({@link get_theme}, {@link set_theme}, {@link
  24. * get_mode}, {@link set_mode}) are thin sugar over the generic
  25. * string accessors; validation lives with the action that owns
  26. * the form, not here — storage accepts any string.
  27. */
  28. public class UserPreferenceService : Object {
  29. private OrmSession db = inject<OrmSession>();
  30. private Connection connection = inject<Connection>();
  31. /**
  32. * The stored value of `key` for `user_id`, or "" when the
  33. * user never set it.
  34. */
  35. public async string get_string(int64 user_id, string key) throws Error {
  36. var row = yield db.query<UserPreference>()
  37. .where(expr("user_id == $0 && key == $1",
  38. elem<int64?>(user_id), elem(key)))
  39. .first_async();
  40. return row != null ? ((!)row).value : "";
  41. }
  42. /**
  43. * Upserts `value` under `key` for `user_id`: one row per
  44. * (user, key), replaced on conflict.
  45. */
  46. public async void set_string(int64 user_id, string key, string value) throws Error {
  47. yield connection.create_command(
  48. "INSERT INTO user_preferences (user_id, key, value)"
  49. + " VALUES (:user_id, :key, :value)"
  50. + " ON CONFLICT(user_id, key) DO UPDATE SET value = excluded.value")
  51. .with_parameter<Invercargill.Element>("user_id", elem<int64?>(user_id))
  52. .with_parameter<Invercargill.Element>("key", elem(key))
  53. .with_parameter<Invercargill.Element>("value", elem(value))
  54. .execute_non_query_async();
  55. }
  56. /** The stored theme slug ("" = the Spry core default). */
  57. public async string get_theme(int64 user_id) throws Error {
  58. return yield get_string(user_id, PREF_THEME);
  59. }
  60. /** Stores the theme slug ("" = the Spry core default). */
  61. public async void set_theme(int64 user_id, string theme) throws Error {
  62. yield set_string(user_id, PREF_THEME, theme);
  63. }
  64. /** The stored colour mode (auto when never set). */
  65. public async string get_mode(int64 user_id) throws Error {
  66. var mode = yield get_string(user_id, PREF_MODE);
  67. return mode.length > 0 ? mode : MODE_DEFAULT;
  68. }
  69. /** Stores the colour mode. */
  70. public async void set_mode(int64 user_id, string mode) throws Error {
  71. yield set_string(user_id, PREF_MODE, mode);
  72. }
  73. }
  74. }