Add flattenthreads experiment

This experiment allows users to flatten the replies in threads, so they
are shown linearly in a chronological way instead of nested.

When the option is enabled, a switch is added to the thread page which
lets the user switch between flattening replies and not flattening them.

Some UI is still missing (see the design document[1]).

[1]: https://docs.google.com/document/d/1P-HanTHxaOFF_FHh0uSv0GIhG1dxWTJTGoT6VPjjvY0/edit

Bug: twpowertools:153
Change-Id: I43f94442cadc12b752700f0e8d974522be621d3e
diff --git a/src/models/Gap.js b/src/models/Gap.js
new file mode 100644
index 0000000..131dfbc
--- /dev/null
+++ b/src/models/Gap.js
@@ -0,0 +1,55 @@
+export default class GapModel {
+  constructor(data) {
+    this.data = data ?? {};
+  }
+
+  getCount() {
+    const a = this.data[1] ?? null;
+    return a != null ? a : 0;
+  }
+
+  setCount(value) {
+    this.data[1] = Number(value);
+  }
+
+  getStartMicroseconds() {
+    return this.data[2] ?? null;
+  }
+
+  setStartMicroseconds(value) {
+    this.data[2] = '' + value;
+  }
+
+  getStartTimestamp() {
+    const a = this.getStartMicroseconds();
+    if (a == null) a = '0';
+    return BigInt(a);
+  }
+
+  getEndMicroseconds() {
+    return this.data[3] ?? null;
+  }
+
+  setEndMicroseconds(value) {
+    this.data[3] = '' + value;
+  }
+
+  getEndTimestamp() {
+    const a = this.getEndMicroseconds();
+    if (a == null) a = '0';
+    return BigInt(a);
+  }
+
+  getParentId() {
+    const a = this.data[4];
+    return a ? Number(a) : 0;
+  }
+
+  setParentId(value) {
+    this.data[4] = '' + value;
+  }
+
+  toRawMessageOrGap() {
+    return {2: this.data};
+  }
+}