Fossil

Check-in [8eb01c314b]
Login

Check-in [8eb01c314b]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:chat: minor UI refinements.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 8eb01c314b0d2d3d1ce4d47b14696af6125706eaf01db1fdb7deefcf2aec4417
User & Date: stephan 2020-12-23 22:58:45.147
Context
2020-12-23
23:27
Several internal cleanups in chat app, e.g. replace document.createXYZ with simpler fossil.dom API. Eliminate assignment to innerHTML, which is widely considered unsafe. ... (check-in: 68da24594f user: stephan tags: trunk)
22:58
chat: minor UI refinements. ... (check-in: 8eb01c314b user: stephan tags: trunk)
22:16
Chat: disable pasting of text when then input field does NOT have focus and fix complete overwriting of input field when pasting and it DOES have focus. Whether or not we should paste to that field when it does not have focus is debatable and possibly violates the Principle of Least Surprise. ... (check-in: 87ff8fe357 user: stephan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/chat.c.
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121





122
123
124
125

126
127
128
129
130
131
132
  @   width: 100%%;
  @   display: flex;
  @   flex-direction: column;
  @ }
  @ #chat-input-line {
  @   display: flex;
  @   flex-direction: row;
  @   margin-bottom: 1em;
  @   align-items: center;
  @ }
  @ #chat-input-line > input[type=submit] {
  @   flex: 1 5 auto;
  @   max-width: 6em;
  @ }
  @ #chat-input-line > input[type=text] {
  @   flex: 5 1 auto;
  @ }
  @ #chat-input-file-area  {
  @   display: flex;
  @   flex-direction: row;
  @   align-items: center;
  @ }
  @ #chat-input-file-area > .help-buttonlet,
  @ #chat-input-file {
  @   align-self: flex-start;
  @   margin-right: 0.5em;
  @   flex: 0 1 auto;





  @ }
  @ #chat-input-file {
  @   border:1px solid rgba(0,0,0,0);/*avoid UI shift during drop-targeting*/
  @   border-radius: 0.25em;

  @ }
  @ #chat-input-file > input {
  @   flex: 1 0 auto;
  @ }
  @ .chat-timestamp {
  @    font-family: monospace;
  @    font-size: 0.8em;







|














|
<



>
>
>
>
>




>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  @   width: 100%%;
  @   display: flex;
  @   flex-direction: column;
  @ }
  @ #chat-input-line {
  @   display: flex;
  @   flex-direction: row;
  @   margin-bottom: 0.25em;
  @   align-items: center;
  @ }
  @ #chat-input-line > input[type=submit] {
  @   flex: 1 5 auto;
  @   max-width: 6em;
  @ }
  @ #chat-input-line > input[type=text] {
  @   flex: 5 1 auto;
  @ }
  @ #chat-input-file-area  {
  @   display: flex;
  @   flex-direction: row;
  @   align-items: center;
  @ }
  @ #chat-input-file-area > .file-selection-wrapper {

  @   align-self: flex-start;
  @   margin-right: 0.5em;
  @   flex: 0 1 auto;
  @   padding: 0.25em 0.25em 0.25em 0;
  @ }
  @ #chat-input-file-area .file-selection-wrapper > * {
  @   vertical-align: middle;
  @   margin: 0;
  @ }
  @ #chat-input-file {
  @   border:1px solid rgba(0,0,0,0);/*avoid UI shift during drop-targeting*/
  @   border-radius: 0.25em;
  @   padding: 0.25em;
  @ }
  @ #chat-input-file > input {
  @   flex: 1 0 auto;
  @ }
  @ .chat-timestamp {
  @    font-family: monospace;
  @    font-size: 0.8em;
150
151
152
153
154
155
156






157

158
159
160
161
162
163
164
  @ <div id='chat-input-area'>
  @   <div id='chat-input-line'>
  @     <input type="text" name="msg" id="sbox" \
  @      placeholder="Type message here.">
  @     <input type="submit" value="Send">
  @   </div>
  @   <div id='chat-input-file-area'>






  @     <input type="file" name="file" id="chat-input-file">

  @     <div id="chat-drop-details"></div>
  @   </div>
  @ </div>
  @ </form>
  @ <hr>

  /* New chat messages get inserted immediately after this element */







>
>
>
>
>
>
|
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  @ <div id='chat-input-area'>
  @   <div id='chat-input-line'>
  @     <input type="text" name="msg" id="sbox" \
  @      placeholder="Type message here.">
  @     <input type="submit" value="Send">
  @   </div>
  @   <div id='chat-input-file-area'>
  @     <div class='file-selection-wrapper'>
  @       <div class='help-buttonlet'>
  @        Select a file to upload, drag/drop a file into this spot,
  @        or paste an image from the clipboard if supported by
  @        your environment.
  @       </div>
  @       <input type="file" name="file" id="chat-input-file">
  @     </div>
  @     <div id="chat-drop-details"></div>
  @   </div>
  @ </div>
  @ </form>
  @ <hr>

  /* New chat messages get inserted immediately after this element */
Changes to src/chat.js.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
(function(){
  const form = document.querySelector('#chat-form');
  let mxMsg = -50;
  if( window.fossilChatInitSize ) mxMsg = -window.fossilChatInitSize;
  const F = window.fossil, D = F.dom;
  const _me = F.user.name;
  /* State for paste and drag/drop */
  const BlobXferState = {
    dropDetails: document.querySelector('#chat-drop-details'),
    blob: undefined
  };
  /** Updates the paste/drop zone with details of the pasted/dropped
      data. */

  const updateDropZoneContent = function(blob){
    const bx = BlobXferState, dd = bx.dropDetails;
    bx.blob = blob;
    D.clearElement(dd);
    if(!blob){
      form.file.value = '';
      return;












|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(function(){
  const form = document.querySelector('#chat-form');
  let mxMsg = -50;
  if( window.fossilChatInitSize ) mxMsg = -window.fossilChatInitSize;
  const F = window.fossil, D = F.dom;
  const _me = F.user.name;
  /* State for paste and drag/drop */
  const BlobXferState = {
    dropDetails: document.querySelector('#chat-drop-details'),
    blob: undefined
  };
  /** Updates the paste/drop zone with details of the pasted/dropped
      data. The argument must be a Blob or Blob-like object (File) or
      it can be falsy to reset/clear that state.*/
  const updateDropZoneContent = function(blob){
    const bx = BlobXferState, dd = bx.dropDetails;
    bx.blob = blob;
    D.clearElement(dd);
    if(!blob){
      form.file.value = '';
      return;
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
          item = items[0];
    if(!item || !item.type) return;
    //console.debug("pasted item =",item);
    if('file'===item.kind){
      updateDropZoneContent(false/*clear prev state*/);
      updateDropZoneContent(items[0].getAsFile());
    }else if(false && 'string'===item.kind){
      /* ----^^^^^ disabled for now:

         The intent here is that if form.msg is not active, populate
         it with this text, but whether populating it from ctrl-v when
         it does not have focus is a feature or a bug is debatable.
      */

      if(document.activeElement !== form.msg){
        /* Overwrite input field if it DOES NOT have focus,
           otherwise let it do its own paste handling. */
        item.getAsString((v)=>form.msg.value = v);
      }
    }
  };
  if(true){/* Add help button for drag/drop/paste zone */
    const help = D.div();
    form.file.parentNode.insertBefore(help, form.file);
    F.helpButtonlets.create(
      help,
      "Select a file to upload, drag/drop a file into this spot, ",
      "or paste an image from the clipboard if supported by ",
      "your environment."

    );
  }
  ////////////////////////////////////////////////////////////
  // File drag/drop visual notification.
  const dropHighlight = form.file /* target zone */;
  const dropEvents = {
    drop: function(ev){







|
<
|
|
|
<
>








<
|
|
|
<
<
<
>







64
65
66
67
68
69
70
71

72
73
74

75
76
77
78
79
80
81
82
83

84
85
86



87
88
89
90
91
92
93
94
          item = items[0];
    if(!item || !item.type) return;
    //console.debug("pasted item =",item);
    if('file'===item.kind){
      updateDropZoneContent(false/*clear prev state*/);
      updateDropZoneContent(items[0].getAsFile());
    }else if(false && 'string'===item.kind){
      /* ----^^^^^ disabled for now: the intent here is that if

         form.msg is not active, populate it with this text, but
         whether populating it from ctrl-v when it does not have focus
         is a feature or a bug is debatable.  It seems useful but may

         violate the Principle of Least Surprise. */
      if(document.activeElement !== form.msg){
        /* Overwrite input field if it DOES NOT have focus,
           otherwise let it do its own paste handling. */
        item.getAsString((v)=>form.msg.value = v);
      }
    }
  };
  if(true){/* Add help button for drag/drop/paste zone */

    form.file.parentNode.insertBefore(
      F.helpButtonlets.create(
        document.querySelector('#chat-input-file-area .help-buttonlet')



      ), form.file
    );
  }
  ////////////////////////////////////////////////////////////
  // File drag/drop visual notification.
  const dropHighlight = form.file /* target zone */;
  const dropEvents = {
    drop: function(ev){
Changes to src/default.css.
1497
1498
1499
1500
1501
1502
1503




  padding: 0 0.5em;
  /*text-align: left; Firefox requires the 'align' attribute */
  margin: 0 0.15em;
  padding: 0 0.5em 0em 0.5em;
  margin-bottom: 0.4em;
  cursor: pointer;
}











>
>
>
>
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  padding: 0 0.5em;
  /*text-align: left; Firefox requires the 'align' attribute */
  margin: 0 0.15em;
  padding: 0 0.5em 0em 0.5em;
  margin-bottom: 0.4em;
  cursor: pointer;
}

body.chat .fossil-tooltip.help-buttonlet-content {
  font-size: 80%;
}