Skip to content

Commit 88a8511

Browse files
committed
[partykit] Longer room Id
1 parent b2ce56d commit 88a8511

File tree

4 files changed

+6
-6
lines changed

4 files changed

+6
-6
lines changed

docs/demos/todo-app/todo-app-v6-collaboration/article.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<nav><ul><li><a href="/">TinyBase</a></li><li><a href="/demos/">Demos</a></li><li><a href="/demos/todo-app/">Todo App</a></li><li><a href="/demos/todo-app/todo-app-v6-collaboration/">Todo App v6 (collaboration)</a></li></ul></nav><section class="s1" id="/demos/todo-app/todo-app-v6-collaboration/" data-id="TA7"><h1>Todo App v6 (collaboration)</h1><iframe srcdoc="&lt;html&gt;&lt;head&gt;&lt;script src=&quot;/umd/react.production.min.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/partysocket.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/tinybase.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/persister-browser.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/persister-partykit-client.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/ui-react.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/ui-react-dom-debug.js&quot;&gt;&lt;/script&gt;&lt;style&gt;@font-face{font-family:Inter;src:url(https://tinybase.org/fonts/inter.woff2) format(&#x27;woff2&#x27;)}body{display:grid;grid-template-columns:35% minmax(0,1fr);grid-template-rows:auto auto 1fr;box-sizing:border-box;font-family:Inter,sans-serif;letter-spacing:-.04rem;grid-gap:1rem .5rem;margin:0;min-height:100vh;padding:1rem}body *{box-sizing:border-box;outline-color:#d81b60}#newTodo{border:1px solid #ccc;display:block;font:inherit;letter-spacing:inherit;padding:.5rem;width:100%}#todos{grid-column:2;grid-row:2/span 2;margin:0;padding:0}#todos .todo{background:#fff;border:1px solid #ccc;display:flex;margin-bottom:.5rem;padding:.5rem}#todos .todo .text{cursor:pointer;flex:1;overflow:hidden;text-overflow:ellipsis;user-select:none;white-space:nowrap}#todos .todo .text::before{content:&#x27;\1F7E0&#x27;;padding:0 .5rem 0 .25rem}#todos .todo .text.done{color:#ccc}#todos .todo .text.done::before{content:&#x27;\2705&#x27;}#types{margin:0}#types .type{cursor:pointer;margin-bottom:.5rem;user-select:none}#types .type.current{color:#d81b60}#todos .todo .type{border:none;color:#777;font:inherit;font-size:.8rem;margin-top:.1rem}#undoRedo{grid-column:1;grid-row:3}#undoRedo #redo,#undoRedo #undo{cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;user-select:none}#undoRedo #redo::before,#undoRedo #undo::before{padding-right:.5rem;vertical-align:middle}#undoRedo #redo.disabled,#undoRedo #undo.disabled{cursor:default;opacity:.3}#undoRedo #undo::before{content:&#x27;\21A9&#x27;}#undoRedo #redo::before{content:&#x27;\21AA&#x27;}#room{grid-column:1;grid-row:3}#room button{font-size:inherit;border:1px solid #ccc;background:#d81b60;color:#fff}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;script&gt;(()=&gt;{const l=React[&quot;createElement&quot;],{createCheckpoints:i,createIndexes:d,createMetrics:c,createStore:u}=TinyBase,{createLocalPersister:p,createSessionPersister:y}=TinyBasePersisterBrowser,h=TinyBasePersisterPartyKitClient[&quot;createPartyKitPersister&quot;],m=PartySocketModule[&quot;default&quot;],{CellView:v,Provider:w,SliceView:e,useAddRowCallback:s,useCell:n,useCheckpoints:C,useCreateCheckpoints:S,useCreateIndexes:g,useCreateMetrics:k,useCreatePersister:I,useCreateStore:b,useMetric:r,useRow:x,useSetCellCallback:f,useSetCheckpointCallback:A,useSetValueCallback:P,useValue:R}=TinyBaseUiReact,{useCallback:T,useEffect:o,useState:B}=React,M=TinyBaseUiReactDomDebug[&quot;StoreInspector&quot;],D=[&quot;Home&quot;,&quot;Work&quot;,&quot;Archived&quot;],L={todos:{text:{type:&quot;string&quot;},done:{type:&quot;boolean&quot;,default:!1},type:{type:&quot;string&quot;,default:&quot;Home&quot;,allow:D}}},E={todos:{0:{text:&quot;Clean the floor&quot;,type:&quot;Home&quot;},1:{text:&quot;Install TinyBase&quot;,type:&quot;Work&quot;},2:{text:&quot;Book holiday&quot;,type:&quot;Archived&quot;}}},t=()=&gt;{const e=b(()=&gt;u().setTablesSchema(L)),t=S(e,i),[o,a]=(I(e,e=&gt;p(e,&quot;todos/store&quot;),[],async e=&gt;{await e.startAutoLoad(E),t.clear(),await e.startAutoSave()},[t]),_());I(e,e=&gt;{if(o)return h(e,new m({host:O,room:o}))},[o],async e=&gt;{e&amp;&amp;(await e.startAutoSave(),await e.startAutoLoad(),t.clear())},[t]);var r=b(()=&gt;u().setValuesSchema({type:{type:&quot;string&quot;,default:&quot;Home&quot;}})),n=(I(r,e=&gt;y(e,&quot;todos/viewStore&quot;),[],async e=&gt;{await e.startAutoLoad(),await e.startAutoSave()}),g(e,e=&gt;d(e).setIndexDefinition(&quot;types&quot;,&quot;todos&quot;,&quot;type&quot;))),s=k(e,e=&gt;{const o=c(e);return o.setMetricDefinition(&quot;pending&quot;,&quot;todos&quot;,&quot;sum&quot;,e=&gt;e(&quot;done&quot;)?0:1),D.forEach(t=&gt;{o.setMetricDefinition(t,&quot;todos&quot;,&quot;sum&quot;,e=&gt;e(&quot;type&quot;)!=t||e(&quot;done&quot;)?0:1)}),o});return l(w,{store:e,storesById:{viewStore:r},indexes:n,metrics:s,checkpoints:t},l(N,null),l(V,null),l(K,null),l(j,{roomId:o,createRoomId:a}),l($,null),l(M,null))},N=(window.addEventListener(&quot;load&quot;,()=&gt;ReactDOM.createRoot(document.body).render(l(t,null))),()=&gt;{var e=r(&quot;pending&quot;);return 0&lt;e?&quot;Todo: &quot;+e:&quot;All done!&quot;}),V=()=&gt;{const[e,t]=B(&quot;&quot;),o=R(&quot;type&quot;,&quot;viewStore&quot;),a=T(({target:{value:e}})=&gt;t(e),[]),r=A(()=&gt;`adding &#x27;${e}&#x27;`,[e]),n=s(&quot;todos&quot;,({which:e,target:{value:t}})=&gt;13==e&amp;&amp;&quot;&quot;!=t?{text:t,type:o}:null,[o],void 0,()=&gt;{t(&quot;&quot;),r()},[t,r]);return l(&quot;input&quot;,{id:&quot;newTodo&quot;,onChange:a,onKeyDown:n,placeholder:&quot;New Todo&quot;,value:e})},$=()=&gt;l(&quot;ul&quot;,{id:&quot;todos&quot;},l(e,{indexId:&quot;types&quot;,sliceId:R(&quot;type&quot;,&quot;viewStore&quot;),rowComponent:a})),a=e=&gt;l(&quot;li&quot;,{className:&quot;todo&quot;},l(H,{...e}),l(W,{...e})),H=({tableId:e,rowId:t})=&gt;{const{done:o,text:a}=x(e,t),r=&quot;text&quot;+(o?&quot; done&quot;:&quot;&quot;),n=f(e,t,&quot;done&quot;,()=&gt;!o,[o]),s=A(()=&gt;`${o?&quot;resuming&quot;:&quot;completing&quot;} &#x27;${a}&#x27;`,[o]),i=T(()=&gt;{n(),s()},[n,s]);return l(&quot;span&quot;,{className:r,onClick:i},l(v,{tableId:e,rowId:t,cellId:&quot;text&quot;}))},K=()=&gt;l(&quot;ul&quot;,{id:&quot;types&quot;},D.map(e=&gt;l(U,{key:e,type:e}))),U=({type:e})=&gt;{var t=r(e),o=R(&quot;type&quot;,&quot;viewStore&quot;),a=P(&quot;type&quot;,()=&gt;e,[e],&quot;viewStore&quot;),o=&quot;type&quot;+(e==o?&quot; current&quot;:&quot;&quot;);return l(&quot;li&quot;,{className:o,onClick:a},e,0&lt;t?` (${t})`:&quot;&quot;)},W=({tableId:e,rowId:t})=&gt;{const o=n(e,t,&quot;type&quot;),a=C(),r=f(e,t,&quot;type&quot;,({target:{value:e}})=&gt;e,[],void 0,(e,t)=&gt;a.addCheckpoint(`changing to &#x27;${t}&#x27;`),[a]);return l(&quot;select&quot;,{className:&quot;type&quot;,onChange:r,value:o},D.map(e=&gt;l(&quot;option&quot;,null,e)))},O=&quot;partykit-todo-server.tinyplexbot.partykit.dev&quot;,_=()=&gt;{const[e,t]=B(&quot;&quot;);return o(()=&gt;{const e=()=&gt;t(parent.location.hash.substring(1));return e(),parent.addEventListener(&quot;hashchange&quot;,e),()=&gt;parent.removeEventListener(&quot;hashchange&quot;,e)},[]),[e,T(()=&gt;{var e=(&quot;&quot;+Math.random()).substring(2,10);parent.history.replaceState(null,null,&quot;#&quot;+e),t(e)},[])]},j=({roomId:e,createRoomId:t})=&gt;l(&quot;div&quot;,{id:&quot;room&quot;},e?l(&quot;a&quot;,{href:&quot;#&quot;+e,target:&quot;_blank&quot;},&quot;Sharing to room &quot;,e):l(&quot;button&quot;,{onClick:t},&quot;Share&quot;))})()&lt;/script&gt;&lt;/html&gt;"></iframe><p>In this version of the Todo app, we use the <a href="https://partykit.io/">PartyKit</a> <a href="/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> to make the application collaborative.</p><p>We&#x27;re making changes to the <a href="/demos/todo-app/todo-app-v5-checkpoints/">Todo App v5 (checkpoints)</a> demo.</p><h3 id="server-implementation">Server Implementation</h3><p>To have a collaborative PartyKit experience, you need to deploy a server. <a href="/">TinyBase</a> provides a ready-made PartyKit server that supports the synchronization and storage needed by client apps like this demo.</p><p>The server implementation for this demo is in the top level &#x27;support&#x27; directory of the <a href="/">TinyBase</a> repo for reference. But don&#x27;t get too excited. It is literally just this:</p><pre><code><span class="keyword">import</span> <span class="punctuation">{</span>TinyBasePartyKitServer<span class="punctuation">}</span> <span class="keyword">from</span> <span class="string">'tinybase/persisters/persister-partykit-server'</span><span class="punctuation">;</span>
1+
<nav><ul><li><a href="/">TinyBase</a></li><li><a href="/demos/">Demos</a></li><li><a href="/demos/todo-app/">Todo App</a></li><li><a href="/demos/todo-app/todo-app-v6-collaboration/">Todo App v6 (collaboration)</a></li></ul></nav><section class="s1" id="/demos/todo-app/todo-app-v6-collaboration/" data-id="TA7"><h1>Todo App v6 (collaboration)</h1><iframe srcdoc="&lt;html&gt;&lt;head&gt;&lt;script src=&quot;/umd/react.production.min.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/partysocket.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/tinybase.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/persister-browser.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/persister-partykit-client.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/ui-react.js&quot;&gt;&lt;/script&gt;&lt;script src=&quot;/umd/ui-react-dom-debug.js&quot;&gt;&lt;/script&gt;&lt;style&gt;@font-face{font-family:Inter;src:url(https://tinybase.org/fonts/inter.woff2) format(&#x27;woff2&#x27;)}body{display:grid;grid-template-columns:35% minmax(0,1fr);grid-template-rows:auto auto 1fr;box-sizing:border-box;font-family:Inter,sans-serif;letter-spacing:-.04rem;grid-gap:1rem .5rem;margin:0;min-height:100vh;padding:1rem}body *{box-sizing:border-box;outline-color:#d81b60}#newTodo{border:1px solid #ccc;display:block;font:inherit;letter-spacing:inherit;padding:.5rem;width:100%}#todos{grid-column:2;grid-row:2/span 2;margin:0;padding:0}#todos .todo{background:#fff;border:1px solid #ccc;display:flex;margin-bottom:.5rem;padding:.5rem}#todos .todo .text{cursor:pointer;flex:1;overflow:hidden;text-overflow:ellipsis;user-select:none;white-space:nowrap}#todos .todo .text::before{content:&#x27;\1F7E0&#x27;;padding:0 .5rem 0 .25rem}#todos .todo .text.done{color:#ccc}#todos .todo .text.done::before{content:&#x27;\2705&#x27;}#types{margin:0}#types .type{cursor:pointer;margin-bottom:.5rem;user-select:none}#types .type.current{color:#d81b60}#todos .todo .type{border:none;color:#777;font:inherit;font-size:.8rem;margin-top:.1rem}#undoRedo{grid-column:1;grid-row:3}#undoRedo #redo,#undoRedo #undo{cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;user-select:none}#undoRedo #redo::before,#undoRedo #undo::before{padding-right:.5rem;vertical-align:middle}#undoRedo #redo.disabled,#undoRedo #undo.disabled{cursor:default;opacity:.3}#undoRedo #undo::before{content:&#x27;\21A9&#x27;}#undoRedo #redo::before{content:&#x27;\21AA&#x27;}#room{grid-column:1;grid-row:3}#room button{font-size:inherit;border:1px solid #ccc;background:#d81b60;color:#fff}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;script&gt;(()=&gt;{const l=React[&quot;createElement&quot;],{createCheckpoints:i,createIndexes:d,createMetrics:c,createStore:u}=TinyBase,{createLocalPersister:p,createSessionPersister:y}=TinyBasePersisterBrowser,h=TinyBasePersisterPartyKitClient[&quot;createPartyKitPersister&quot;],m=PartySocketModule[&quot;default&quot;],{CellView:v,Provider:w,SliceView:e,useAddRowCallback:s,useCell:n,useCheckpoints:C,useCreateCheckpoints:S,useCreateIndexes:g,useCreateMetrics:k,useCreatePersister:I,useCreateStore:b,useMetric:r,useRow:x,useSetCellCallback:f,useSetCheckpointCallback:A,useSetValueCallback:P,useValue:R}=TinyBaseUiReact,{useCallback:T,useEffect:o,useState:B}=React,M=TinyBaseUiReactDomDebug[&quot;StoreInspector&quot;],D=[&quot;Home&quot;,&quot;Work&quot;,&quot;Archived&quot;],L={todos:{text:{type:&quot;string&quot;},done:{type:&quot;boolean&quot;,default:!1},type:{type:&quot;string&quot;,default:&quot;Home&quot;,allow:D}}},E={todos:{0:{text:&quot;Clean the floor&quot;,type:&quot;Home&quot;},1:{text:&quot;Install TinyBase&quot;,type:&quot;Work&quot;},2:{text:&quot;Book holiday&quot;,type:&quot;Archived&quot;}}},t=()=&gt;{const e=b(()=&gt;u().setTablesSchema(L)),t=S(e,i),[o,a]=(I(e,e=&gt;p(e,&quot;todos/store&quot;),[],async e=&gt;{await e.startAutoLoad(E),t.clear(),await e.startAutoSave()},[t]),_());I(e,e=&gt;{if(o)return h(e,new m({host:O,room:o}))},[o],async e=&gt;{e&amp;&amp;(await e.startAutoSave(),await e.startAutoLoad(),t.clear())},[t]);var r=b(()=&gt;u().setValuesSchema({type:{type:&quot;string&quot;,default:&quot;Home&quot;}})),n=(I(r,e=&gt;y(e,&quot;todos/viewStore&quot;),[],async e=&gt;{await e.startAutoLoad(),await e.startAutoSave()}),g(e,e=&gt;d(e).setIndexDefinition(&quot;types&quot;,&quot;todos&quot;,&quot;type&quot;))),s=k(e,e=&gt;{const o=c(e);return o.setMetricDefinition(&quot;pending&quot;,&quot;todos&quot;,&quot;sum&quot;,e=&gt;e(&quot;done&quot;)?0:1),D.forEach(t=&gt;{o.setMetricDefinition(t,&quot;todos&quot;,&quot;sum&quot;,e=&gt;e(&quot;type&quot;)!=t||e(&quot;done&quot;)?0:1)}),o});return l(w,{store:e,storesById:{viewStore:r},indexes:n,metrics:s,checkpoints:t},l(N,null),l(V,null),l(K,null),l(j,{roomId:o,createRoomId:a}),l($,null),l(M,null))},N=(window.addEventListener(&quot;load&quot;,()=&gt;ReactDOM.createRoot(document.body).render(l(t,null))),()=&gt;{var e=r(&quot;pending&quot;);return 0&lt;e?&quot;Todo: &quot;+e:&quot;All done!&quot;}),V=()=&gt;{const[e,t]=B(&quot;&quot;),o=R(&quot;type&quot;,&quot;viewStore&quot;),a=T(({target:{value:e}})=&gt;t(e),[]),r=A(()=&gt;`adding &#x27;${e}&#x27;`,[e]),n=s(&quot;todos&quot;,({which:e,target:{value:t}})=&gt;13==e&amp;&amp;&quot;&quot;!=t?{text:t,type:o}:null,[o],void 0,()=&gt;{t(&quot;&quot;),r()},[t,r]);return l(&quot;input&quot;,{id:&quot;newTodo&quot;,onChange:a,onKeyDown:n,placeholder:&quot;New Todo&quot;,value:e})},$=()=&gt;l(&quot;ul&quot;,{id:&quot;todos&quot;},l(e,{indexId:&quot;types&quot;,sliceId:R(&quot;type&quot;,&quot;viewStore&quot;),rowComponent:a})),a=e=&gt;l(&quot;li&quot;,{className:&quot;todo&quot;},l(H,{...e}),l(W,{...e})),H=({tableId:e,rowId:t})=&gt;{const{done:o,text:a}=x(e,t),r=&quot;text&quot;+(o?&quot; done&quot;:&quot;&quot;),n=f(e,t,&quot;done&quot;,()=&gt;!o,[o]),s=A(()=&gt;`${o?&quot;resuming&quot;:&quot;completing&quot;} &#x27;${a}&#x27;`,[o]),i=T(()=&gt;{n(),s()},[n,s]);return l(&quot;span&quot;,{className:r,onClick:i},l(v,{tableId:e,rowId:t,cellId:&quot;text&quot;}))},K=()=&gt;l(&quot;ul&quot;,{id:&quot;types&quot;},D.map(e=&gt;l(U,{key:e,type:e}))),U=({type:e})=&gt;{var t=r(e),o=R(&quot;type&quot;,&quot;viewStore&quot;),a=P(&quot;type&quot;,()=&gt;e,[e],&quot;viewStore&quot;),o=&quot;type&quot;+(e==o?&quot; current&quot;:&quot;&quot;);return l(&quot;li&quot;,{className:o,onClick:a},e,0&lt;t?` (${t})`:&quot;&quot;)},W=({tableId:e,rowId:t})=&gt;{const o=n(e,t,&quot;type&quot;),a=C(),r=f(e,t,&quot;type&quot;,({target:{value:e}})=&gt;e,[],void 0,(e,t)=&gt;a.addCheckpoint(`changing to &#x27;${t}&#x27;`),[a]);return l(&quot;select&quot;,{className:&quot;type&quot;,onChange:r,value:o},D.map(e=&gt;l(&quot;option&quot;,null,e)))},O=&quot;partykit-todo-server.tinyplexbot.partykit.dev&quot;,_=()=&gt;{const[e,t]=B(&quot;&quot;);return o(()=&gt;{const e=()=&gt;t(parent.location.hash.substring(1));return e(),parent.addEventListener(&quot;hashchange&quot;,e),()=&gt;parent.removeEventListener(&quot;hashchange&quot;,e)},[]),[e,T(()=&gt;{var e=(&quot;&quot;+Math.random()).substring(2,12);parent.history.replaceState(null,null,&quot;#&quot;+e),t(e)},[])]},j=({roomId:e,createRoomId:t})=&gt;l(&quot;div&quot;,{id:&quot;room&quot;},e?l(&quot;a&quot;,{href:&quot;#&quot;+e,target:&quot;_blank&quot;},&quot;Sharing to room &quot;,e):l(&quot;button&quot;,{onClick:t},&quot;Share&quot;))})()&lt;/script&gt;&lt;/html&gt;"></iframe><p>In this version of the Todo app, we use the <a href="https://partykit.io/">PartyKit</a> <a href="/api/persisters/interfaces/persister/persister/"><code>Persister</code></a> to make the application collaborative.</p><p>We&#x27;re making changes to the <a href="/demos/todo-app/todo-app-v5-checkpoints/">Todo App v5 (checkpoints)</a> demo.</p><h3 id="server-implementation">Server Implementation</h3><p>To have a collaborative PartyKit experience, you need to deploy a server. <a href="/">TinyBase</a> provides a ready-made PartyKit server that supports the synchronization and storage needed by client apps like this demo.</p><p>The server implementation for this demo is in the top level &#x27;support&#x27; directory of the <a href="/">TinyBase</a> repo for reference. But don&#x27;t get too excited. It is literally just this:</p><pre><code><span class="keyword">import</span> <span class="punctuation">{</span>TinyBasePartyKitServer<span class="punctuation">}</span> <span class="keyword">from</span> <span class="string">'tinybase/persisters/persister-partykit-server'</span><span class="punctuation">;</span>
22

33
<span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="class-name">extends</span> TinyBasePartyKitServer <span class="punctuation">{</span><span class="punctuation">}</span>
44
</code></pre><p>The TinyBasePartyKitServer class does all the work for synchronizing and storing data in the PartyKit cloud. Obviously if you need to enhance your server, you should just be able to extend that TinyBasePartyKitServer class accordingly.</p><p>For the purposes of this demo, this server has been deployed to partykit.dev, and so on the client, we need to set its address:</p><pre><code><span class="keyword">const</span> <span class="constant">PARTYKIT_HOST</span> <span class="operator">=</span> <span class="string">'partykit-todo-server.tinyplexbot.partykit.dev'</span><span class="punctuation">;</span>
@@ -23,7 +23,7 @@
2323
<span class="keyword">return</span> <span class="punctuation">[</span>
2424
roomId<span class="punctuation">,</span>
2525
<span class="function">useCallback</span><span class="punctuation">(</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">=></span> <span class="punctuation">{</span>
26-
<span class="keyword">const</span> newRoomId <span class="operator">=</span> <span class="punctuation">(</span><span class="string">''</span> <span class="operator">+</span> Math<span class="punctuation">.</span><span class="function">random</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">.</span><span class="function">substring</span><span class="punctuation">(</span><span class="number">2</span><span class="punctuation">,</span> <span class="number">10</span><span class="punctuation">)</span><span class="punctuation">;</span>
26+
<span class="keyword">const</span> newRoomId <span class="operator">=</span> <span class="punctuation">(</span><span class="string">''</span> <span class="operator">+</span> Math<span class="punctuation">.</span><span class="function">random</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">.</span><span class="function">substring</span><span class="punctuation">(</span><span class="number">2</span><span class="punctuation">,</span> <span class="number">12</span><span class="punctuation">)</span><span class="punctuation">;</span>
2727
parent<span class="punctuation">.</span>history<span class="punctuation">.</span><span class="function">replaceState</span><span class="punctuation">(</span><span class="keyword">null</span><span class="punctuation">,</span> <span class="keyword">null</span><span class="punctuation">,</span> <span class="string">'#'</span> <span class="operator">+</span> newRoomId<span class="punctuation">)</span><span class="punctuation">;</span>
2828
<span class="function">setRoomId</span><span class="punctuation">(</span>newRoomId<span class="punctuation">)</span><span class="punctuation">;</span>
2929
<span class="punctuation">}</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">)</span><span class="punctuation">,</span>

0 commit comments

Comments
 (0)