The frontend/UI server, written in JS using the MarkoJS library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.1 KiB

  1. const EventEmitter = require("events");
  2. let linkSignal = null;
  3. module.exports = class {
  4. onCreate(input) {
  5. this.state = {
  6. shortName: "",
  7. name: "",
  8. text: "",
  9. nameSuffix: "",
  10. modal: null,
  11. removed: false,
  12. multipart: false,
  13. anchored: false,
  14. }
  15. this.mounted = false;
  16. this.updatePost(input)
  17. }
  18. open(modal) {
  19. this.state.modal = modal
  20. }
  21. close() {
  22. this.state.modal = null
  23. }
  24. move(toPosition) {
  25. this.emit("move", toPosition)
  26. }
  27. remove() {
  28. this.state.removed = true
  29. this.emit("remove")
  30. }
  31. edited(data) {
  32. this.emit("edited", data)
  33. }
  34. onInput(input) {
  35. if (this.state == null) {
  36. return
  37. }
  38. const timediff = Date.parse(input.post.time) - Date.parse(input.prev.time)
  39. this.state.multipart = (input.post.nick == input.prev.nick && input.prev.multipart !== false) && (Math.abs(timediff) < 60000);
  40. this.updatePost(input)
  41. }
  42. onMount() {
  43. this.linkSignalCallback = () => {
  44. this.state.anchored = false
  45. }
  46. if (linkSignal == null) {
  47. linkSignal = new EventEmitter()
  48. linkSignal.setMaxListeners(10000)
  49. }
  50. linkSignal.on("signal", this.linkSignalCallback)
  51. this.state.anchored = window.location.hash.slice(1) === this.input.post.id;
  52. }
  53. onUnmount() {
  54. linkSignal.removeListener("signal", this.linkSignalCallback)
  55. }
  56. link() {
  57. linkSignal.emit("signal")
  58. this.state.anchored = true
  59. }
  60. updatePost(input) {
  61. this.state.shortName = input.post.nick.split("_").shift()
  62. this.state.name = input.post.nick
  63. this.state.nameSuffix = ""
  64. this.state.text = input.post.text.replace(/\x02/g, "**").replace(/\x1D/g, "_").trim();
  65. if (this.state.text.startsWith("|")) {
  66. this.state.name = ""
  67. this.state.text = this.state.text.slice(1).trim();
  68. }
  69. if (input.post.kind === "text" && !this.state.text.includes("\"") && !this.state.text.includes("|")) {
  70. const colonIndex = this.state.text.indexOf(": ");
  71. if (colonIndex != -1 && colonIndex < this.state.text.indexOf(" ")) {
  72. this.state.text = this.state.text.replace(": ", ": \"") + "\"";
  73. } else {
  74. this.state.text = '"' + this.state.text + '"'
  75. }
  76. }
  77. if (this.state.text.charAt(0) == this.state.text.charAt(0).toUpperCase()) {
  78. this.state.name = ""
  79. }
  80. if (!input.post.nick.startsWith("=")) {
  81. const postNick = input.post.nick.replace("'s", "").replace("s'", "s")
  82. for (const character of input.characters) {
  83. for (const nick of character.nicks) {
  84. if (nick === postNick) {
  85. this.state.name = character.name
  86. this.state.shortName = character.shortName
  87. if (input.post.nick.endsWith("'s") || input.post.nick.endsWith("'")) {
  88. this.state.nameSuffix = (character.shortName.endsWith("s") || character.shortName.endsWith("z")) ? "'" : "'s"
  89. }
  90. return
  91. }
  92. }
  93. }
  94. }
  95. }
  96. kindClass(prefix) {
  97. if (this.input.post == null) {
  98. return
  99. }
  100. return `${prefix}${this.input.post.kind.replace(".", "-")}`
  101. }
  102. }