simple_chat 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95df7692026ee5d37a07aeed5d7c9313d3fb3aaf366e63aee01bc708022933a2
4
- data.tar.gz: 8ddc33579c622c06f8b144d3e2122ce44e4be7a30be30efe4955ae82036ffb81
3
+ metadata.gz: 052a3dab195ce41f61b0beafac3f73bd45667d9d68c5a655cc7e30dbedf1c60f
4
+ data.tar.gz: 297cfdea187fbf2b8cc695455a3d7b5d2692f6d805ae0b5921bb1e9385f16619
5
5
  SHA512:
6
- metadata.gz: c5d5030a14a5c6eaf1c4ba7810b7d46ea8482b6c5ac0e8bdf2949af90c3a8571ec95dbe5d38b8bba3dc703bda524cf773633fb03f98d7be39832da2cbeff3fbe
7
- data.tar.gz: 2dfb34e8ff9b0241fe1ef2bf1ea1eab7435113c6d179c9f26611d5d4e67008639470bc35d958ab7ddb72e83d1c5c1bf96e9fdb7e026917b2f5cd6cc39ffeb41c
6
+ metadata.gz: 0be1d16263e85472e5d2bec5902cf72c8f2bd233608e6c3c77c91794658f99de4e6494f5311835983621ce8245d57c0ad7d55dbf321f29c6ec0422b177257fd7
7
+ data.tar.gz: 9a849c67eb3992bd750101107c93859458ae7d5b1b609fabede999c0bfb2771ad88a140dbc07b11f1eef8a9721662e765b2bfc52c4f759af028bbcfce1bf850a
@@ -16,16 +16,17 @@
16
16
  --color-blue-100: oklch(93.2% 0.032 255.585);
17
17
  --color-blue-500: oklch(62.3% 0.214 259.815);
18
18
  --color-blue-600: oklch(54.6% 0.245 262.881);
19
- --color-blue-700: oklch(48.8% 0.243 264.376);
20
19
  --color-blue-800: oklch(42.4% 0.199 265.638);
21
20
  --color-indigo-500: oklch(58.5% 0.233 277.117);
22
21
  --color-indigo-600: oklch(51.1% 0.262 276.966);
23
22
  --color-gray-50: oklch(98.5% 0.002 247.839);
23
+ --color-gray-100: oklch(96.7% 0.003 264.542);
24
24
  --color-gray-200: oklch(92.8% 0.006 264.531);
25
25
  --color-gray-300: oklch(87.2% 0.01 258.338);
26
26
  --color-gray-400: oklch(70.7% 0.022 261.325);
27
27
  --color-gray-500: oklch(55.1% 0.027 264.364);
28
28
  --color-gray-600: oklch(44.6% 0.03 256.802);
29
+ --color-gray-700: oklch(37.3% 0.034 259.733);
29
30
  --color-gray-800: oklch(27.8% 0.033 256.848);
30
31
  --color-gray-900: oklch(21% 0.034 264.665);
31
32
  --color-white: #fff;
@@ -39,11 +40,16 @@
39
40
  --text-base--line-height: calc(1.5 / 1);
40
41
  --text-2xl: 1.5rem;
41
42
  --text-2xl--line-height: calc(2 / 1.5);
43
+ --text-3xl: 1.875rem;
44
+ --text-3xl--line-height: calc(2.25 / 1.875);
42
45
  --font-weight-medium: 500;
43
46
  --font-weight-semibold: 600;
44
47
  --font-weight-bold: 700;
48
+ --tracking-tight: -0.025em;
45
49
  --radius-md: 0.375rem;
46
50
  --radius-lg: 0.5rem;
51
+ --default-transition-duration: 150ms;
52
+ --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
47
53
  --default-font-family: var(--font-sans);
48
54
  --default-mono-font-family: var(--font-mono);
49
55
  }
@@ -214,6 +220,9 @@
214
220
  .relative {
215
221
  position: relative;
216
222
  }
223
+ .inset-0 {
224
+ inset: calc(var(--spacing) * 0);
225
+ }
217
226
  .inset-x-0 {
218
227
  inset-inline: calc(var(--spacing) * 0);
219
228
  }
@@ -235,15 +244,45 @@
235
244
  .left-0 {
236
245
  left: calc(var(--spacing) * 0);
237
246
  }
247
+ .container {
248
+ width: 100%;
249
+ @media (width >= 40rem) {
250
+ max-width: 40rem;
251
+ }
252
+ @media (width >= 48rem) {
253
+ max-width: 48rem;
254
+ }
255
+ @media (width >= 64rem) {
256
+ max-width: 64rem;
257
+ }
258
+ @media (width >= 80rem) {
259
+ max-width: 80rem;
260
+ }
261
+ @media (width >= 96rem) {
262
+ max-width: 96rem;
263
+ }
264
+ }
238
265
  .mx-auto {
239
266
  margin-inline: auto;
240
267
  }
268
+ .mt-1 {
269
+ margin-top: calc(var(--spacing) * 1);
270
+ }
271
+ .mt-2 {
272
+ margin-top: calc(var(--spacing) * 2);
273
+ }
241
274
  .mt-3 {
242
275
  margin-top: calc(var(--spacing) * 3);
243
276
  }
244
277
  .mt-6 {
245
278
  margin-top: calc(var(--spacing) * 6);
246
279
  }
280
+ .mt-8 {
281
+ margin-top: calc(var(--spacing) * 8);
282
+ }
283
+ .mt-10 {
284
+ margin-top: calc(var(--spacing) * 10);
285
+ }
247
286
  .mb-2 {
248
287
  margin-bottom: calc(var(--spacing) * 2);
249
288
  }
@@ -253,21 +292,40 @@
253
292
  .mb-6 {
254
293
  margin-bottom: calc(var(--spacing) * 6);
255
294
  }
295
+ .mb-10 {
296
+ margin-bottom: calc(var(--spacing) * 10);
297
+ }
256
298
  .ml-1 {
257
299
  margin-left: calc(var(--spacing) * 1);
258
300
  }
301
+ .ml-5 {
302
+ margin-left: calc(var(--spacing) * 5);
303
+ }
259
304
  .block {
260
305
  display: block;
261
306
  }
262
307
  .flex {
263
308
  display: flex;
264
309
  }
310
+ .flow-root {
311
+ display: flow-root;
312
+ }
313
+ .grid {
314
+ display: grid;
315
+ }
265
316
  .inline {
266
317
  display: inline;
267
318
  }
319
+ .inline-flex {
320
+ display: inline-flex;
321
+ }
268
322
  .table {
269
323
  display: table;
270
324
  }
325
+ .size-0\.5 {
326
+ width: calc(var(--spacing) * 0.5);
327
+ height: calc(var(--spacing) * 0.5);
328
+ }
271
329
  .size-6 {
272
330
  width: calc(var(--spacing) * 6);
273
331
  height: calc(var(--spacing) * 6);
@@ -278,6 +336,9 @@
278
336
  .w-6 {
279
337
  width: calc(var(--spacing) * 6);
280
338
  }
339
+ .w-16 {
340
+ width: calc(var(--spacing) * 16);
341
+ }
281
342
  .w-full {
282
343
  width: 100%;
283
344
  }
@@ -287,6 +348,9 @@
287
348
  .max-w-4xl {
288
349
  max-width: var(--container-4xl);
289
350
  }
351
+ .min-w-0 {
352
+ min-width: calc(var(--spacing) * 0);
353
+ }
290
354
  .flex-auto {
291
355
  flex: auto;
292
356
  }
@@ -302,9 +366,18 @@
302
366
  .resize-none {
303
367
  resize: none;
304
368
  }
369
+ .list-disc {
370
+ list-style-type: disc;
371
+ }
372
+ .grid-cols-1 {
373
+ grid-template-columns: repeat(1, minmax(0, 1fr));
374
+ }
305
375
  .flex-col {
306
376
  flex-direction: column;
307
377
  }
378
+ .flex-wrap {
379
+ flex-wrap: wrap;
380
+ }
308
381
  .items-center {
309
382
  align-items: center;
310
383
  }
@@ -320,6 +393,9 @@
320
393
  .gap-2 {
321
394
  gap: calc(var(--spacing) * 2);
322
395
  }
396
+ .gap-3 {
397
+ gap: calc(var(--spacing) * 3);
398
+ }
323
399
  .space-y-6 {
324
400
  :where(& > :not(:last-child)) {
325
401
  --tw-space-y-reverse: 0;
@@ -327,12 +403,58 @@
327
403
  margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));
328
404
  }
329
405
  }
406
+ .space-y-12 {
407
+ :where(& > :not(:last-child)) {
408
+ --tw-space-y-reverse: 0;
409
+ margin-block-start: calc(calc(var(--spacing) * 12) * var(--tw-space-y-reverse));
410
+ margin-block-end: calc(calc(var(--spacing) * 12) * calc(1 - var(--tw-space-y-reverse)));
411
+ }
412
+ }
413
+ .gap-x-2 {
414
+ column-gap: calc(var(--spacing) * 2);
415
+ }
416
+ .gap-x-2\.5 {
417
+ column-gap: calc(var(--spacing) * 2.5);
418
+ }
330
419
  .gap-x-3 {
331
420
  column-gap: calc(var(--spacing) * 3);
332
421
  }
333
422
  .gap-x-4 {
334
423
  column-gap: calc(var(--spacing) * 4);
335
424
  }
425
+ .gap-x-6 {
426
+ column-gap: calc(var(--spacing) * 6);
427
+ }
428
+ .gap-x-8 {
429
+ column-gap: calc(var(--spacing) * 8);
430
+ }
431
+ .-space-x-0\.5 {
432
+ :where(& > :not(:last-child)) {
433
+ --tw-space-x-reverse: 0;
434
+ margin-inline-start: calc(calc(var(--spacing) * -0.5) * var(--tw-space-x-reverse));
435
+ margin-inline-end: calc(calc(var(--spacing) * -0.5) * calc(1 - var(--tw-space-x-reverse)));
436
+ }
437
+ }
438
+ .gap-y-4 {
439
+ row-gap: calc(var(--spacing) * 4);
440
+ }
441
+ .gap-y-8 {
442
+ row-gap: calc(var(--spacing) * 8);
443
+ }
444
+ .divide-y {
445
+ :where(& > :not(:last-child)) {
446
+ --tw-divide-y-reverse: 0;
447
+ border-bottom-style: var(--tw-border-style);
448
+ border-top-style: var(--tw-border-style);
449
+ border-top-width: calc(1px * var(--tw-divide-y-reverse));
450
+ border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
451
+ }
452
+ }
453
+ .divide-gray-100 {
454
+ :where(& > :not(:last-child)) {
455
+ border-color: var(--color-gray-100);
456
+ }
457
+ }
336
458
  .overflow-hidden {
337
459
  overflow: hidden;
338
460
  }
@@ -366,6 +488,12 @@
366
488
  .border-gray-300 {
367
489
  border-color: var(--color-gray-300);
368
490
  }
491
+ .border-gray-900\/10 {
492
+ border-color: color-mix(in srgb, oklch(21% 0.034 264.665) 10%, transparent);
493
+ @supports (color: color-mix(in lab, red, red)) {
494
+ border-color: color-mix(in oklab, var(--color-gray-900) 10%, transparent);
495
+ }
496
+ }
369
497
  .bg-blue-50\/50 {
370
498
  background-color: color-mix(in srgb, oklch(97% 0.014 254.604) 50%, transparent);
371
499
  @supports (color: color-mix(in lab, red, red)) {
@@ -378,6 +506,9 @@
378
506
  .bg-gray-200 {
379
507
  background-color: var(--color-gray-200);
380
508
  }
509
+ .bg-indigo-600 {
510
+ background-color: var(--color-indigo-600);
511
+ }
381
512
  .bg-red-50 {
382
513
  background-color: var(--color-red-50);
383
514
  }
@@ -387,6 +518,9 @@
387
518
  .bg-white {
388
519
  background-color: var(--color-white);
389
520
  }
521
+ .fill-current {
522
+ fill: currentcolor;
523
+ }
390
524
  .p-3 {
391
525
  padding: calc(var(--spacing) * 3);
392
526
  }
@@ -414,6 +548,9 @@
414
548
  .py-2 {
415
549
  padding-block: calc(var(--spacing) * 2);
416
550
  }
551
+ .py-5 {
552
+ padding-block: calc(var(--spacing) * 5);
553
+ }
417
554
  .py-8 {
418
555
  padding-block: calc(var(--spacing) * 8);
419
556
  }
@@ -423,6 +560,9 @@
423
560
  .pb-4 {
424
561
  padding-bottom: calc(var(--spacing) * 4);
425
562
  }
563
+ .pb-5 {
564
+ padding-bottom: calc(var(--spacing) * 5);
565
+ }
426
566
  .pb-12 {
427
567
  padding-bottom: calc(var(--spacing) * 12);
428
568
  }
@@ -483,6 +623,9 @@
483
623
  .text-gray-600 {
484
624
  color: var(--color-gray-600);
485
625
  }
626
+ .text-gray-700 {
627
+ color: var(--color-gray-700);
628
+ }
486
629
  .text-gray-900 {
487
630
  color: var(--color-gray-900);
488
631
  }
@@ -492,6 +635,9 @@
492
635
  .text-red-600 {
493
636
  color: var(--color-red-600);
494
637
  }
638
+ .text-white {
639
+ color: var(--color-white);
640
+ }
495
641
  .shadow {
496
642
  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
497
643
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -500,10 +646,18 @@
500
646
  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
501
647
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
502
648
  }
649
+ .shadow-xs {
650
+ --tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.05));
651
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
652
+ }
503
653
  .ring-1 {
504
654
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
505
655
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
506
656
  }
657
+ .inset-ring {
658
+ --tw-inset-ring-shadow: inset 0 0 0 1px var(--tw-inset-ring-color, currentcolor);
659
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
660
+ }
507
661
  .ring-blue-100 {
508
662
  --tw-ring-color: var(--color-blue-100);
509
663
  }
@@ -513,16 +667,31 @@
513
667
  .ring-gray-300 {
514
668
  --tw-ring-color: var(--color-gray-300);
515
669
  }
670
+ .inset-ring-gray-300 {
671
+ --tw-inset-ring-color: var(--color-gray-300);
672
+ }
516
673
  .outline-1 {
517
674
  outline-style: var(--tw-outline-style);
518
675
  outline-width: 1px;
519
676
  }
677
+ .outline-2 {
678
+ outline-style: var(--tw-outline-style);
679
+ outline-width: 2px;
680
+ }
520
681
  .-outline-offset-1 {
521
682
  outline-offset: calc(1px * -1);
522
683
  }
523
684
  .outline-gray-300 {
524
685
  outline-color: var(--color-gray-300);
525
686
  }
687
+ .outline-white {
688
+ outline-color: var(--color-white);
689
+ }
690
+ .transition-colors {
691
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
692
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
693
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
694
+ }
526
695
  .ring-inset {
527
696
  --tw-ring-inset: inset;
528
697
  }
@@ -554,6 +723,13 @@
554
723
  }
555
724
  }
556
725
  }
726
+ .hover\:bg-indigo-500 {
727
+ &:hover {
728
+ @media (hover: hover) {
729
+ background-color: var(--color-indigo-500);
730
+ }
731
+ }
732
+ }
557
733
  .hover\:text-blue-800 {
558
734
  &:hover {
559
735
  @media (hover: hover) {
@@ -582,6 +758,13 @@
582
758
  }
583
759
  }
584
760
  }
761
+ .hover\:underline {
762
+ &:hover {
763
+ @media (hover: hover) {
764
+ text-decoration-line: underline;
765
+ }
766
+ }
767
+ }
585
768
  .focus\:border-indigo-500 {
586
769
  &:focus {
587
770
  border-color: var(--color-indigo-500);
@@ -592,17 +775,99 @@
592
775
  --tw-ring-color: var(--color-indigo-500);
593
776
  }
594
777
  }
778
+ .focus\:outline-2 {
779
+ &:focus {
780
+ outline-style: var(--tw-outline-style);
781
+ outline-width: 2px;
782
+ }
783
+ }
784
+ .focus\:-outline-offset-2 {
785
+ &:focus {
786
+ outline-offset: calc(2px * -1);
787
+ }
788
+ }
789
+ .focus\:outline-indigo-600 {
790
+ &:focus {
791
+ outline-color: var(--color-indigo-600);
792
+ }
793
+ }
595
794
  .focus\:outline-none {
596
795
  &:focus {
597
796
  --tw-outline-style: none;
598
797
  outline-style: none;
599
798
  }
600
799
  }
800
+ .focus-visible\:outline-2 {
801
+ &:focus-visible {
802
+ outline-style: var(--tw-outline-style);
803
+ outline-width: 2px;
804
+ }
805
+ }
806
+ .focus-visible\:outline-offset-2 {
807
+ &:focus-visible {
808
+ outline-offset: 2px;
809
+ }
810
+ }
811
+ .focus-visible\:outline-indigo-600 {
812
+ &:focus-visible {
813
+ outline-color: var(--color-indigo-600);
814
+ }
815
+ }
816
+ .sm\:col-span-4 {
817
+ @media (width >= 40rem) {
818
+ grid-column: span 4 / span 4;
819
+ }
820
+ }
821
+ .sm\:mt-0 {
822
+ @media (width >= 40rem) {
823
+ margin-top: calc(var(--spacing) * 0);
824
+ }
825
+ }
826
+ .sm\:ml-4 {
827
+ @media (width >= 40rem) {
828
+ margin-left: calc(var(--spacing) * 4);
829
+ }
830
+ }
831
+ .sm\:flex {
832
+ @media (width >= 40rem) {
833
+ display: flex;
834
+ }
835
+ }
836
+ .sm\:w-auto {
837
+ @media (width >= 40rem) {
838
+ width: auto;
839
+ }
840
+ }
841
+ .sm\:grid-cols-6 {
842
+ @media (width >= 40rem) {
843
+ grid-template-columns: repeat(6, minmax(0, 1fr));
844
+ }
845
+ }
846
+ .sm\:flex-nowrap {
847
+ @media (width >= 40rem) {
848
+ flex-wrap: nowrap;
849
+ }
850
+ }
851
+ .sm\:items-center {
852
+ @media (width >= 40rem) {
853
+ align-items: center;
854
+ }
855
+ }
856
+ .sm\:justify-between {
857
+ @media (width >= 40rem) {
858
+ justify-content: space-between;
859
+ }
860
+ }
601
861
  .sm\:rounded-lg {
602
862
  @media (width >= 40rem) {
603
863
  border-radius: var(--radius-lg);
604
864
  }
605
865
  }
866
+ .sm\:px-6 {
867
+ @media (width >= 40rem) {
868
+ padding-inline: calc(var(--spacing) * 6);
869
+ }
870
+ }
606
871
  .sm\:text-sm {
607
872
  @media (width >= 40rem) {
608
873
  font-size: var(--text-sm);
@@ -615,12 +880,27 @@
615
880
  line-height: calc(var(--spacing) * 6);
616
881
  }
617
882
  }
883
+ .lg\:px-8 {
884
+ @media (width >= 64rem) {
885
+ padding-inline: calc(var(--spacing) * 8);
886
+ }
887
+ }
618
888
  }
619
889
  @property --tw-space-y-reverse {
620
890
  syntax: "*";
621
891
  inherits: false;
622
892
  initial-value: 0;
623
893
  }
894
+ @property --tw-space-x-reverse {
895
+ syntax: "*";
896
+ inherits: false;
897
+ initial-value: 0;
898
+ }
899
+ @property --tw-divide-y-reverse {
900
+ syntax: "*";
901
+ inherits: false;
902
+ initial-value: 0;
903
+ }
624
904
  @property --tw-border-style {
625
905
  syntax: "*";
626
906
  inherits: false;
@@ -704,6 +984,8 @@
704
984
  @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
705
985
  *, ::before, ::after, ::backdrop {
706
986
  --tw-space-y-reverse: 0;
987
+ --tw-space-x-reverse: 0;
988
+ --tw-divide-y-reverse: 0;
707
989
  --tw-border-style: solid;
708
990
  --tw-font-weight: initial;
709
991
  --tw-shadow: 0 0 #0000;
@@ -6,7 +6,7 @@ module SimpleChat
6
6
  # GET /chat_rooms
7
7
  def index
8
8
  if simple_chat_current_user
9
- @chat_rooms = ChatRoom.for_user(simple_chat_current_user)
9
+ @chat_rooms = ChatRoom.for_user(simple_chat_current_user).includes(:messages, chat_members: :user)
10
10
  else
11
11
  @chat_rooms = ChatRoom.none
12
12
  end
@@ -14,7 +14,7 @@ module SimpleChat
14
14
 
15
15
  # GET /chat_rooms/1
16
16
  def show
17
- @messages = @chat_room.messages.select(&:persisted?)
17
+ @messages = @chat_room.messages.includes(:user).select(&:persisted?)
18
18
  @message = @chat_room.messages.build
19
19
  end
20
20
 
@@ -2,14 +2,41 @@ module SimpleChat
2
2
  class ChatRoom < ApplicationRecord
3
3
  has_many :messages, dependent: :destroy
4
4
  has_many :chat_members, dependent: :destroy
5
- validates :title, uniqueness: true
5
+ validates :title, presence: true, uniqueness: true
6
6
 
7
7
  scope :for_user, ->(user) { joins(:chat_members).where(simple_chat_chat_members: { user_id: user.id }) }
8
8
 
9
+ def last_message
10
+ messages.last
11
+ end
12
+
13
+ def last_message_user_name
14
+ return nil unless last_message
15
+ user_name(last_message.user)
16
+ end
17
+
18
+ def member_avatars(limit = 5)
19
+ chat_members.limit(limit).map do |member|
20
+ name = user_name(member.user)
21
+ { name: name, url: "https://ui-avatars.com/api/?name=#{CGI.escape(name)}&background=random" }
22
+ end
23
+ end
24
+
25
+ def messages_count
26
+ messages.count
27
+ end
28
+
9
29
  def is_member?(user)
10
30
  chat_members.exists?(user: user)
11
31
  end
12
32
 
33
+ private
34
+
35
+ def user_name(user)
36
+ return "Unknown" unless user
37
+ user.respond_to?(:name) ? user.name : "User ##{user.id}"
38
+ end
39
+
13
40
  private
14
41
  def is_group_chat
15
42
  chat_members.count > 2
@@ -3,6 +3,16 @@ module SimpleChat
3
3
  belongs_to :chat_room
4
4
  belongs_to :user, class_name: SimpleChat.configuration.chat_user_model
5
5
 
6
+ def user_name
7
+ return "Unknown" unless user
8
+ user.respond_to?(:name) ? user.name : "User ##{user_id}"
9
+ end
10
+
11
+ def user_initials
12
+ return "?" unless user
13
+ user.respond_to?(:name) ? user.name[0].upcase : user_id.to_s
14
+ end
15
+
6
16
  after_create_commit :broadcast_to_members
7
17
 
8
18
  private
@@ -1,7 +1,42 @@
1
- <div id="<%= dom_id chat_room %>">
2
- <div>
3
- <strong>Title:</strong>
4
- <%= chat_room.title %>
1
+ <li id="<%= dom_id chat_room %>" class="relative flex flex-wrap items-center justify-between gap-x-6 gap-y-4 py-5 sm:flex-nowrap hover:bg-gray-50 transition-colors">
2
+ <div class="min-w-0 flex-auto">
3
+ <p class="text-sm/6 font-semibold text-gray-900">
4
+ <%= link_to chat_room, class: "hover:underline focus:outline-none" do %>
5
+ <span class="absolute inset-0" aria-hidden="true"></span>
6
+ <%= chat_room.title %>
7
+ <% end %>
8
+ </p>
9
+ <div class="mt-1 flex items-center gap-x-2 text-xs/5 text-gray-700">
10
+ <% if last_message = chat_room.last_message %>
11
+ <p>
12
+ Last message by <%= chat_room.last_message_user_name %>
13
+ </p>
14
+ <svg viewBox="0 0 2 2" class="size-0.5 fill-current">
15
+ <circle r="1" cx="1" cy="1" />
16
+ </svg>
17
+ <p><time datetime="<%= last_message.created_at.iso8601 %>"><%= time_ago_in_words(last_message.created_at) %> ago</time></p>
18
+ <% else %>
19
+ <p>No messages yet</p>
20
+ <% end %>
21
+ </div>
5
22
  </div>
6
-
7
- </div>
23
+ <dl class="flex w-full flex-none justify-between gap-x-8 sm:w-auto">
24
+ <div class="flex -space-x-0.5">
25
+ <dt class="sr-only">Members</dt>
26
+ <% chat_room.member_avatars.each do |avatar| %>
27
+ <dd>
28
+ <img src="<%= avatar[:url] %>" alt="<%= avatar[:name] %>" class="size-6 rounded-full bg-gray-50 outline-2 outline-white" />
29
+ </dd>
30
+ <% end %>
31
+ </div>
32
+ <div class="flex w-16 gap-x-2.5">
33
+ <dt>
34
+ <span class="sr-only">Total messages</span>
35
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" data-slot="icon" aria-hidden="true" class="size-6 text-gray-400">
36
+ <path d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.076-4.076a1.526 1.526 0 0 1 1.037-.443 48.282 48.282 0 0 0 5.68-.494c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" stroke-linecap="round" stroke-linejoin="round" />
37
+ </svg>
38
+ </dt>
39
+ <dd class="text-sm/6 text-gray-900"><%= chat_room.messages_count %></dd>
40
+ </div>
41
+ </dl>
42
+ </li>
@@ -1,9 +1,9 @@
1
- <%= form_with(model: chat_room) do |form| %>
1
+ <%= form_with(model: chat_room, class: "space-y-12") do |form| %>
2
2
  <% if chat_room.errors.any? %>
3
- <div style="color: red">
4
- <h2><%= pluralize(chat_room.errors.count, "error") %> prohibited this chat_room from being saved:</h2>
3
+ <div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-lg">
4
+ <h2><%= pluralize(chat_room.errors.count, "error") %> prohibited this chat room from being saved:</h2>
5
5
 
6
- <ul>
6
+ <ul class="list-disc ml-5">
7
7
  <% chat_room.errors.each do |error| %>
8
8
  <li><%= error.full_message %></li>
9
9
  <% end %>
@@ -11,12 +11,18 @@
11
11
  </div>
12
12
  <% end %>
13
13
 
14
- <div>
15
- <%= form.label :title, style: "display: block" %>
16
- <%= form.text_field :title %>
14
+ <div class="border-b border-gray-900/10 pb-12">
15
+ <div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
16
+ <div class="sm:col-span-4">
17
+ <%= form.label :title, class: "block text-sm font-medium text-gray-900" %>
18
+ <div class="mt-2">
19
+ <%= form.text_field :title, class: "block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6" %>
20
+ </div>
21
+ </div>
22
+ </div>
17
23
  </div>
18
24
 
19
- <div>
20
- <%= form.submit %>
25
+ <div class="mt-6 flex items-center justify-end gap-x-6">
26
+ <%= form.submit "Save", class: "rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 cursor-pointer" %>
21
27
  </div>
22
28
  <% end %>
@@ -1,12 +1,12 @@
1
1
  <% content_for :title, "Editing chat room" %>
2
2
 
3
- <h1>Editing chat room</h1>
4
-
5
- <%= render "form", chat_room: @chat_room %>
6
-
7
- <br>
8
-
9
- <div>
10
- <%= link_to "Show this chat room", @chat_room %> |
11
- <%= link_to "Back to chat rooms", chat_rooms_path %>
3
+ <div class="mx-auto max-w-4xl px-4 py-8">
4
+ <div class="border-b border-gray-200 pb-5 sm:flex sm:items-center sm:justify-between mb-10">
5
+ <h3 class="text-base font-semibold text-gray-900">Edit chat room</h3>
6
+ <div class="mt-3 flex sm:mt-0 sm:ml-4 gap-3">
7
+ <%= link_to "Back", @chat_room, class: "hidden text-sm/6 text-gray-900 sm:block" %>
8
+ </div>
9
+ </div>
10
+
11
+ <%= render "form", chat_room: @chat_room %>
12
12
  </div>
@@ -1,14 +1,15 @@
1
1
  <% content_for :title, "Chat rooms" %>
2
2
 
3
- <h1>Chat rooms</h1>
4
-
5
- <div id="chat_rooms">
6
- <% @chat_rooms.each do |chat_room| %>
7
- <%= render chat_room %>
8
- <p>
9
- <%= link_to "Show this chat room", chat_room %>
10
- </p>
11
- <% end %>
3
+ <div class="mx-auto max-w-4xl px-4 py-8 sm:px-6 lg:px-8">
4
+ <div class="border-b border-gray-200 pb-5 sm:flex sm:items-center sm:justify-between">
5
+ <h3 class="text-base font-semibold text-gray-900">Chat rooms</h3>
6
+ <div class="mt-3 sm:mt-0 sm:ml-4">
7
+ <%= link_to "New chat room", new_chat_room_path, class: "inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" %>
8
+ </div>
9
+ </div>
10
+ <div class="mt-8 flow-root">
11
+ <ul id="chat_rooms" role="list" class="divide-y divide-gray-100">
12
+ <%= render @chat_rooms %>
13
+ </ul>
14
+ </div>
12
15
  </div>
13
-
14
- <%= link_to "New chat room", new_chat_room_path %>
@@ -1,11 +1,12 @@
1
1
  <% content_for :title, "New chat room" %>
2
2
 
3
- <h1>New chat room</h1>
4
-
5
- <%= render "form", chat_room: @chat_room %>
6
-
7
- <br>
8
-
9
- <div>
10
- <%= link_to "Back to chat rooms", chat_rooms_path %>
3
+ <div class="mx-auto max-w-4xl px-4 py-8">
4
+ <div class="border-b border-gray-200 pb-5 sm:flex sm:items-center sm:justify-between mb-10">
5
+ <h3 class="text-base font-semibold text-gray-900">New chat room</h3>
6
+ <div class="mt-3 flex sm:mt-0 sm:ml-4">
7
+ <%= link_to "Back", chat_rooms_path, class: "hidden text-sm/6 text-gray-900 sm:block" %>
8
+ </div>
9
+ </div>
10
+
11
+ <%= render "form", chat_room: @chat_room %>
11
12
  </div>
@@ -4,8 +4,8 @@
4
4
  <%= @chat_room.title %>
5
5
  </h1>
6
6
  <div class="flex gap-2">
7
- <%= link_to "Edit", edit_chat_room_path(@chat_room), class: "text-sm text-blue-600 hover:text-blue-800" %>
8
- <%= link_to "Back", chat_rooms_path, class: "text-sm text-gray-600 hover:text-gray-800" %>
7
+ <%= link_to "Edit", edit_chat_room_path(@chat_room), class: "hidden font-semibold sm:block text-sm text-blue-600 hover:text-blue-800" %>
8
+ <%= link_to "Back", chat_rooms_path, class: "text-sm text-gray-600 hover:text-gray-800 hidden font-semibold sm:block" %>
9
9
  </div>
10
10
  </div>
11
11
 
@@ -5,18 +5,18 @@
5
5
  <div class="w-px bg-gray-200"></div>
6
6
  </div>
7
7
 
8
- <div class="relative mt-3 size-6 flex-none rounded-full bg-gray-50 flex items-center justify-center ring-1 ring-gray-200">
9
- <span class="text-[10px] font-bold text-gray-500"><%= message.user.respond_to?(:name) ? message.user.name[0].upcase : message.user_id %></span>
10
- </div>
8
+ <div class="relative mt-3 size-6 flex-none rounded-full bg-gray-50 flex items-center justify-center ring-1 ring-gray-200">
9
+ <span class="text-[10px] font-bold text-gray-500"><%= message.user_initials %></span>
10
+ </div>
11
11
 
12
- <div class="flex-auto rounded-md p-3 ring-1 ring-gray-200 ring-inset <%= message.user == current_user ? 'bg-blue-50/50 ring-blue-100' : 'bg-white' %>">
13
- <div class="flex justify-between gap-x-4">
14
- <div class="py-0.5 text-xs/5 text-gray-500">
15
- <span class="font-medium text-gray-900"><%= message.user.respond_to?(:name) ? message.user.name : "User ##{message.user_id}" %></span>
16
- <% if message.user == current_user %>
17
- <span class="ml-1 text-[10px] text-blue-500 font-semibold">(You)</span>
18
- <% end %>
19
- </div>
12
+ <div class="flex-auto rounded-md p-3 ring-1 ring-gray-200 ring-inset <%= message.user == current_user ? 'bg-blue-50/50 ring-blue-100' : 'bg-white' %>">
13
+ <div class="flex justify-between gap-x-4">
14
+ <div class="py-0.5 text-xs/5 text-gray-500">
15
+ <span class="font-medium text-gray-900"><%= message.user_name %></span>
16
+ <% if message.user == current_user %>
17
+ <span class="ml-1 text-[10px] text-blue-500 font-semibold">(You)</span>
18
+ <% end %>
19
+ </div>
20
20
  <time datetime="<%= message.created_at.iso8601 %>" class="flex-none py-0.5 text-xs/5 text-gray-400">
21
21
  <%= time_ago_in_words(message.created_at) %> ago
22
22
  </time>
@@ -1,3 +1,3 @@
1
1
  module SimpleChat
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - YiSheng, Lee