@shaxpir/duiduidui-models 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,90 +0,0 @@
1
- import { Doc } from '@shaxpir/sharedb/lib/client';
2
- import { CompactDateTime, MultiClock } from "@shaxpir/shaxpir-common";
3
- import { ShareSync, ShareSyncFactory } from '../repo';
4
- import { Content, ContentBody, ContentId, ContentMeta } from "./Content";
5
- import { ContentKind } from './ContentKind';
6
- import { BatchOperation } from './Operation';
7
-
8
- export interface LastSync {
9
- at_utc_time:CompactDateTime|null;
10
- }
11
-
12
- export interface TagFilterConfig {
13
- any?: string[];
14
- all?: string[];
15
- none?: string[];
16
- }
17
-
18
- export interface DevicePayload {
19
- last_sync?:LastSync;
20
- chinese_font?: string;
21
- raw_search_text?: string;
22
- star_filter?: boolean;
23
- tag_filter?: TagFilterConfig;
24
- }
25
-
26
- export interface DeviceBody extends ContentBody {
27
- meta:ContentMeta;
28
- payload:DevicePayload;
29
- }
30
-
31
- export class Device extends Content {
32
-
33
- public static create(
34
- userId:ContentId,
35
- deviceId:ContentId
36
- ):Device {
37
- const now = MultiClock.now();
38
- return ShareSyncFactory.get().createContent(
39
- {
40
- meta : {
41
- ref : deviceId,
42
- kind : ContentKind.DEVICE,
43
- id : deviceId,
44
- owner : userId,
45
- created_at : now,
46
- updated_at : now
47
- },
48
- payload : {
49
- last_sync : { at_utc_time : null as CompactDateTime }
50
- }
51
- }
52
- ) as Device;
53
- }
54
-
55
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
56
- super(doc, shouldAcquire, shareSync);
57
- }
58
-
59
- public get payload():DevicePayload {
60
- this.checkDisposed("Device.payload");
61
- return this.doc.data.payload as DevicePayload;
62
- }
63
-
64
- public get lastSyncAtUtcTime():CompactDateTime {
65
- this.checkDisposed("Device.lastSyncAtUtcTime");
66
- return this.payload.last_sync.at_utc_time as CompactDateTime;
67
- }
68
- public setLastSyncAtUtcTime(value:CompactDateTime):void {
69
- this.checkDisposed("Device.setLastSyncAtUtcTime");
70
- if (this.lastSyncAtUtcTime !== value) {
71
- const batch = new BatchOperation(this);
72
- batch.setPathValue([ 'payload', 'last_sync', 'at_utc_time' ] , value);
73
- batch.commit();
74
- }
75
- }
76
-
77
- public get chineseFont():string {
78
- this.checkDisposed("Device.chineseFont");
79
- return this.payload.chinese_font || 'Huninn';
80
- }
81
-
82
- public setChineseFont(value:string):void {
83
- this.checkDisposed("Device.setChineseFont");
84
- if (this.chineseFont !== value) {
85
- const batch = new BatchOperation(this);
86
- batch.setPathValue([ 'payload', 'chinese_font' ] , value);
87
- batch.commit();
88
- }
89
- }
90
- }
@@ -1,4 +0,0 @@
1
- export interface GeoLocation {
2
- lat:number;
3
- lon:number;
4
- }
@@ -1,16 +0,0 @@
1
- export interface Hanzi {
2
- text: string;
3
- rank: number;
4
- components: Array<{
5
- text: string;
6
- meaning: string;
7
- pinyin: string;
8
- }>;
9
- radical: string;
10
- radical_analysis: string;
11
- component_analysis: string;
12
- }
13
-
14
- export interface BuiltInHanzi extends Hanzi {
15
- id: number;
16
- }
@@ -1,171 +0,0 @@
1
- import { Doc } from '@shaxpir/sharedb/lib/client';
2
- import { CachingHasher, CompactDateTime, SingleTime, Time } from '@shaxpir/shaxpir-common';
3
- import { ShareSync, ShareSyncFactory } from '../repo';
4
- import { Content, ContentId, ContentRef } from "./Content";
5
- import { ContentKind } from './ContentKind';
6
- import { Model } from './Model';
7
- import { BatchOperation } from './Operation';
8
-
9
- export interface ManifestMeta {
10
- kind:ContentKind;
11
- ref:ContentRef;
12
- updated_at:SingleTime;
13
- owner:ContentId;
14
- }
15
-
16
- export interface ManifestBody {
17
- meta:ManifestMeta;
18
- payload:ManifestPayload;
19
- }
20
-
21
- export interface ManifestEntry {
22
- kind:ContentKind;
23
- ref:ContentRef;
24
- at_utc_time:CompactDateTime;
25
- }
26
-
27
- export interface ManifestPayload {
28
- device:any;
29
- media:any;
30
- metric:any;
31
- profile:any;
32
- progress:any;
33
- session:any;
34
- term:any;
35
- user:any;
36
- workspace:any;
37
- }
38
-
39
- export class Manifest extends Model {
40
-
41
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
42
- super(doc, shouldAcquire, shareSync);
43
- }
44
-
45
- public static makeManifestId(userId:ContentId):ContentId {
46
- return CachingHasher.makeMd5Base62Hash(userId + "-" + ContentKind.MANIFEST) as ContentId;
47
- }
48
-
49
- public static create(userId:ContentId):Manifest {
50
- const now:CompactDateTime = Time.utc();
51
- const manifestId = Manifest.makeManifestId(userId);
52
- return ShareSyncFactory.get().createManifest({
53
- meta : {
54
- kind : ContentKind.MANIFEST,
55
- ref : manifestId,
56
- updated_at : {
57
- utc_time : now
58
- },
59
- owner : userId
60
- },
61
- payload: {
62
- device : {},
63
- media : {},
64
- metric : {},
65
- profile : {},
66
- progress : {},
67
- session : {},
68
- term : {},
69
- user: {},
70
- workspace : {}
71
- }
72
- });
73
- }
74
-
75
- public get meta():ManifestMeta {
76
- this.checkDisposed("Manifest.meta");
77
- return this.doc.data.meta as ManifestMeta;
78
- }
79
-
80
- public get owner():ContentId {
81
- this.checkDisposed("Manifest.userId");
82
- return this.doc.data.meta.owner as ContentId;
83
- }
84
-
85
- public canUserView(userId:ContentId):boolean {
86
- this.checkDisposed("Manifest.canUserView");
87
- return this.doc.data.meta.owner === userId;
88
- }
89
-
90
- public doesContentExist(kind:ContentKind, ref:ContentRef):boolean {
91
- this.checkDisposed("Manifest.doesContentExist");
92
- return this.doc.data &&
93
- this.doc.data.payload &&
94
- this.doc.data.payload[kind] &&
95
- this.doc.data.payload[kind][ref];
96
- }
97
-
98
- public getUtcTimeOf(kind:ContentKind, ref:ContentRef):CompactDateTime {
99
- this.checkDisposed("Manifest.getTimestampOf");
100
- if (this.doesContentExist(kind, ref)) {
101
- return this.doc.data.payload[kind][ref] as CompactDateTime;
102
- }
103
- return null as CompactDateTime;
104
- }
105
-
106
- public getAllEntries():ManifestEntry[] {
107
- return this.getAllEntriesWhere(() => true);
108
- }
109
-
110
- public getAllEntriesWhere(
111
- predicate?:(entry:ManifestEntry) => boolean
112
- ):ManifestEntry[] {
113
- const entries = [] as ManifestEntry[];
114
- if (this.exists() && this.doc.data.payload) {
115
- Manifest.forEachEntry(
116
- this.doc.data as ManifestBody,
117
- (entry:ManifestEntry) => {
118
- if (!predicate || predicate(entry)) {
119
- entries.push(entry);
120
- }
121
- }
122
- );
123
- }
124
- return entries;
125
- }
126
-
127
- public update(content:Content):void {
128
- this.checkDisposed("Manifest.update");
129
- content.acquire().then(() => {
130
-
131
- const kind:ContentKind = content.kind;
132
- const contentRef:ContentId = content.ref;
133
-
134
- const timestamp:CompactDateTime = content.updatedAt.utc_time;
135
- const batch = new BatchOperation(this, content.meta.updated_at);
136
-
137
- // Update the embedded timestamp of this content item
138
- batch.setPathValue([ 'payload', kind, contentRef ], timestamp);
139
-
140
- batch.commit();
141
- content.release();
142
- });
143
- }
144
-
145
- public static forEachEntry(
146
- body:ManifestBody,
147
- callback:(entry:ManifestEntry) => void
148
- ):void {
149
- const kinds = Object.keys(body.payload);
150
- for (let i = 0; i < kinds.length; i++) {
151
- const kind = kinds[i] as ContentKind;
152
- const manifestPayload = (body.payload as any)[kind];
153
- const refs = Object.keys(manifestPayload);
154
- for (let j = 0; j < refs.length; j++) {
155
- const ref = refs[j] as ContentRef;
156
- const timestamp = manifestPayload[ref] as CompactDateTime;
157
- if (ref && timestamp) {
158
- const entry = {
159
- kind : kind,
160
- ref : ref,
161
- at_utc_time : timestamp
162
- };
163
- callback(entry);
164
- } else {
165
- console.error(`manifest with missing ref or timestamp: ${JSON.stringify(body)}`);
166
- }
167
- }
168
- }
169
- }
170
-
171
- }
@@ -1,125 +0,0 @@
1
- import { Doc } from '@shaxpir/sharedb/lib/client';
2
- import { MultiClock } from '@shaxpir/shaxpir-common';
3
- import { ShareSync, ShareSyncFactory } from '../repo';
4
- import { Content, ContentBody, ContentId, ContentMeta } from "./Content";
5
- import { ContentKind } from './ContentKind';
6
-
7
- export interface MediaDimensions {
8
- width:number;
9
- height:number;
10
- }
11
-
12
- export interface MediaCropping extends MediaDimensions {
13
- offset_top:number;
14
- offset_left:number;
15
- }
16
-
17
- export interface MediaPayload extends MediaDimensions {
18
- extension:string;
19
- bytes:number;
20
- }
21
-
22
- export interface MediaBody extends ContentBody {
23
- meta:ContentMeta;
24
- payload:MediaPayload;
25
- }
26
-
27
- export class Media extends Content {
28
-
29
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
30
- super(doc, shouldAcquire, shareSync);
31
- }
32
-
33
- public get payload():MediaPayload {
34
- this.checkDisposed("Media.payload");
35
- return this.doc.data.payload as MediaPayload;
36
- }
37
-
38
- public static create(
39
- userId:ContentId,
40
- mediaId:ContentId,
41
- payload:MediaPayload
42
- ):Media {
43
- const now = MultiClock.now();
44
- return ShareSyncFactory.get().createContent({
45
- meta : {
46
- ref : mediaId,
47
- kind : ContentKind.MEDIA,
48
- id : mediaId,
49
- owner : userId,
50
- created_at : now,
51
- updated_at : now
52
- },
53
- payload : payload
54
- }) as Media;
55
- }
56
-
57
- get bytes():number {
58
- this.checkDisposed("Media.bytes");
59
- return this.payload.bytes;
60
- }
61
-
62
- get width():number {
63
- this.checkDisposed("Media.width");
64
- return this.payload.width;
65
- }
66
-
67
- get height():number {
68
- this.checkDisposed("Media.height");
69
- return this.payload.height;
70
- }
71
-
72
- get extension():string {
73
- this.checkDisposed("Media.extension");
74
- return this.payload.extension;
75
- }
76
-
77
- public get mediaType():string {
78
- this.checkDisposed("Media.mediaType");
79
- const extension:string = this.extension;
80
- if (extension === "jpg" || extension === "jpeg") {
81
- return "image/jpeg";
82
- } else if (extension === "png") {
83
- return "image/png";
84
- } else if (extension === "gif") {
85
- return "image/gif";
86
- } else if (extension === "svg") {
87
- return "image/svg+xml";
88
- } else if (extension === "bmp") {
89
- return "image/bmp";
90
- }
91
- return "image/" + extension;
92
- }
93
-
94
- public scaleToFit(boxSize:number, cropping:MediaCropping):MediaCropping {
95
- this.checkDisposed("Media.scaleToFit");
96
- const zoom = boxSize / cropping.width;
97
- const scaledWidth = Math.floor(this.width * zoom);
98
- const scaledHeight = Math.floor(this.height * zoom);
99
- const offsetLeft = -Math.floor(cropping.offset_left * zoom);
100
- const offsetTop = -Math.floor(cropping.offset_top * zoom);
101
- return {
102
- "offset_top" : offsetTop,
103
- "offset_left" : offsetLeft,
104
- "width" : scaledWidth,
105
- "height" : scaledHeight
106
- };
107
- }
108
-
109
- public static makeDefaultCropping(media:Media):MediaCropping {
110
- const width = media.width;
111
- const height = media.height;
112
- const isLandscapeOrSquare:boolean = width >= height;
113
- const isPortraitOrSquare:boolean = height >= width;
114
- const croppingOffsetTop:number = isLandscapeOrSquare ? 0 : Math.floor((height - width) / 2);
115
- const croppingOffsetLeft:number = isPortraitOrSquare ? 0 : Math.floor((width - height) / 2);
116
- const croppingWidth:number = isLandscapeOrSquare ? height : width;
117
- const croppingHeight:number = isPortraitOrSquare ? width : height;
118
- return {
119
- offset_top : croppingOffsetTop,
120
- offset_left : croppingOffsetLeft,
121
- width : croppingWidth,
122
- height : croppingHeight
123
- };
124
- }
125
- }
@@ -1,233 +0,0 @@
1
- import { Doc } from '@shaxpir/sharedb/lib/client';
2
- import { CachingHasher, CompactDate, CompactDateTime, MultiClock, Time } from "@shaxpir/shaxpir-common";
3
- import dayjs from 'dayjs';
4
- import utc from 'dayjs/plugin/utc';
5
- import { ShareSync, ShareSyncFactory } from '../repo';
6
- import { Content, ContentBody, ContentId, ContentMeta } from "./Content";
7
- import { ContentKind } from './ContentKind';
8
- import { BatchOperation } from './Operation';
9
-
10
- dayjs.extend(utc);
11
-
12
- export enum MetricName {
13
- WORD_COUNT = "word_count",
14
- MINUTES_WRITING = "minutes_writing"
15
- }
16
-
17
- export interface MetricEntry {
18
- date:CompactDate;
19
- amount:number;
20
- }
21
-
22
- export interface MetricPayload {
23
- metric_name:string;
24
- min_date:CompactDate;
25
- max_date:CompactDate;
26
- entries:{[key:string]:number};
27
- }
28
-
29
- export interface MetricBody extends ContentBody {
30
- meta:ContentMeta;
31
- payload:MetricPayload;
32
- }
33
-
34
- export class Metric extends Content {
35
-
36
- public static makeMetricId(userId:ContentId, metricName:MetricName):ContentId {
37
- return CachingHasher.makeMd5Base62Hash(userId + "-metric-" + metricName) as ContentId;
38
- }
39
-
40
- public static create(
41
- userId:ContentId,
42
- metricName:MetricName,
43
- entries:{[key:string]:number}
44
- ):Metric {
45
-
46
- const metricId = Metric.makeMetricId(userId, metricName);
47
-
48
- // Find the min and max dates
49
- let minDate:CompactDate = null as CompactDateTime;
50
- let maxDate:CompactDate = null as CompactDateTime;
51
- for (let d of Object.keys(entries)) {
52
- const date:CompactDate = d as CompactDate;
53
- if (minDate === null || Time.compareDate(date, minDate) < 0) {
54
- minDate = date;
55
- }
56
- if (maxDate === null || Time.compareDate(date, maxDate) > 0) {
57
- maxDate = date;
58
- }
59
- }
60
- const now = MultiClock.now();
61
- return ShareSyncFactory.get().createContent(
62
- {
63
- meta : {
64
- ref : metricId,
65
- kind : ContentKind.METRIC,
66
- id : metricId,
67
- owner : userId,
68
- created_at : now,
69
- updated_at : now
70
- },
71
- payload : {
72
- metric_name : metricName,
73
- min_date : minDate,
74
- max_date : maxDate,
75
- entries : entries
76
- }
77
- }
78
- ) as Metric;
79
- }
80
-
81
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
82
- super(doc, shouldAcquire, shareSync);
83
- }
84
-
85
- public get payload():MetricPayload {
86
- this.checkDisposed("Metric.payload");
87
- return this.doc.data.payload as MetricPayload;
88
- }
89
-
90
- public get metricName():string {
91
- this.checkDisposed("Metric.name");
92
- return this.payload.metric_name;
93
- }
94
-
95
- public get minDate():CompactDate {
96
- this.checkDisposed("Metric.minDate");
97
- return this.payload.min_date;
98
- }
99
-
100
- public get maxDate():CompactDate {
101
- this.checkDisposed("Metric.maxDate");
102
- return this.payload.max_date;
103
- }
104
-
105
- public get length():number {
106
- this.checkDisposed("Metric.length");
107
- const minMoment:any = dayjs.utc(this.minDate, Time.DATE_FORMAT);
108
- const maxMoment:any = dayjs.utc(this.maxDate, Time.DATE_FORMAT);
109
- return Math.abs(maxMoment.diff(minMoment, "days")) + 1;
110
- }
111
-
112
- public get(index:number):MetricEntry {
113
- this.checkDisposed("Metric.get");
114
- if (index === 0) {
115
- return {
116
- date: this.minDate,
117
- amount: this.forDate(this.minDate)
118
- };
119
- } else {
120
- const minMoment:any = dayjs.utc(this.minDate, Time.DATE_FORMAT);
121
- const offsetDate:CompactDate = minMoment.add(index, 'days').format(Time.DATE_FORMAT) as CompactDate;
122
- return {
123
- date: offsetDate,
124
- amount: this.forDate(offsetDate)
125
- };
126
- }
127
- }
128
-
129
- public sumBetween(minDate:CompactDate, maxDate:CompactDate):number {
130
- this.checkDisposed("Metric.sumBetween");
131
- let sum:number = 0;
132
- const dates:CompactDate[] = Time.datesBetween(minDate, maxDate);
133
- for (let i = 0, len = dates.length; i < len; i++) {
134
- const date:CompactDate = dates[i];
135
- sum += this.forDate(date);
136
- }
137
- return sum;
138
- }
139
-
140
- public forDate(date:CompactDate):number {
141
- this.checkDisposed("Metric.forDate");
142
- const map:any = this.payload.entries;
143
- if (map.hasOwnProperty(date)) {
144
- return map[date as string];
145
- }
146
- return 0.0;
147
- }
148
-
149
- public nonZeroDayCount():number {
150
- this.checkDisposed("Metric.nonZeroDayCount");
151
- let count:number = 0;
152
- const map:any = this.payload.entries;
153
- for (let date of Object.keys(map)) {
154
- if (map[date] !== 0.0) {
155
- count++;
156
- }
157
- }
158
- return count;
159
- }
160
-
161
- public setDateAmount(date:CompactDate, amount:number):void {
162
- this.checkDisposed("Metric.setDateAmount");
163
-
164
- const prevMinDate = this.payload.min_date;
165
- const prevMaxDate = this.payload.max_date;
166
-
167
- const batch = new BatchOperation(this);
168
- batch.setPathValue([ 'payload', 'entries', date ] , amount);
169
-
170
- if (prevMinDate === null || Time.compareDate(date, prevMinDate) < 0) {
171
- batch.setPathValue([ 'payload', 'min_date' ] , date);
172
- }
173
- if (prevMaxDate === null || Time.compareDate(date, prevMaxDate) > 0) {
174
- batch.setPathValue([ 'payload', 'max_date' ] , date);
175
- }
176
-
177
- batch.commit();
178
- }
179
-
180
- public incrementDateAmounts(dateAmounts:{[key:string]:number}):void {
181
- this.checkDisposed("Metric.incrementDateAmounts");
182
-
183
- const prevMinDate = this.payload.min_date;
184
- const prevMaxDate = this.payload.max_date;
185
-
186
- let minDate = prevMinDate;
187
- let maxDate = prevMaxDate;
188
-
189
- const batch = new BatchOperation(this);
190
-
191
- const dates = Object.keys(dateAmounts);
192
- for (let i = 0; i < dates.length; i++) {
193
- const date:CompactDate = dates[i] as CompactDate;
194
-
195
- const prevAmount:number = this.forDate(date);
196
- const newAmount:number = dateAmounts[date];
197
-
198
- batch.setPathValue([ 'payload', 'entries', date ] , prevAmount + newAmount);
199
-
200
- if (minDate === null || Time.compareDate(date, minDate) < 0) {
201
- minDate = date;
202
- }
203
- if (maxDate === null || Time.compareDate(date, maxDate) > 0) {
204
- maxDate = date;
205
- }
206
- }
207
-
208
- if (minDate != prevMinDate) {
209
- batch.setPathValue([ 'payload', 'min_date' ] , minDate);
210
- }
211
- if (maxDate != prevMaxDate) {
212
- batch.setPathValue([ 'payload', 'max_date' ] , maxDate);
213
- }
214
-
215
- batch.commit();
216
- }
217
-
218
- public static forEachEntry(
219
- body:MetricBody,
220
- callback:(entry:MetricEntry) => void
221
- ):void {
222
- const dates = Object.keys(body.payload.entries);
223
- for (let i = 0; i < dates.length; i++) {
224
- const date = dates[i] as CompactDate;
225
- const amount = body.payload.entries[date] as number;
226
- callback({
227
- date : date,
228
- amount : amount
229
- });
230
- }
231
- }
232
-
233
- }