nixamp 0.28.37 → 0.28.41
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.
- package/README.md +6 -1
- package/backtoschool/dist/assets/{ar-CmpEhms8.js → ar-BQPKp0M2.js} +1 -1
- package/backtoschool/dist/assets/{cs-BiiJOLTm.js → cs-DjJnhGNB.js} +1 -1
- package/{web/dist/assets/da-M4GDhrcC.js → backtoschool/dist/assets/da-CbTvkIH7.js} +1 -1
- package/{web/dist/assets/de-D7yI8cd_.js → backtoschool/dist/assets/de-SsCkny26.js} +1 -1
- package/backtoschool/dist/assets/{es-BwQQh_C8.js → es-BBlBPcq1.js} +1 -1
- package/backtoschool/dist/assets/{fi-DKPYMsbo.js → fi-ffo35_4W.js} +1 -1
- package/backtoschool/dist/assets/{fr-DNekMW0h.js → fr-BVvavrk7.js} +1 -1
- package/{web/dist/assets/hi-DO7CO-fI.js → backtoschool/dist/assets/hi-DDy_zxu6.js} +1 -1
- package/{web/dist/assets/hls-3VKVEQE3-BCxdTCEU.js → backtoschool/dist/assets/hls-3VKVEQE3-QZWXCWjR.js} +1 -1
- package/backtoschool/dist/assets/hls-n74Cnh8A.js +42 -0
- package/backtoschool/dist/assets/{hu-gcw9ouWH.js → hu-BoJj7pZa.js} +1 -1
- package/backtoschool/dist/assets/{id-Bz51zxz6.js → id-CXN9gchF.js} +1 -1
- package/backtoschool/dist/assets/index-BaiHu9CD.css +1 -0
- package/backtoschool/dist/assets/index-Dovv39gH.js +112 -0
- package/backtoschool/dist/assets/{it-jO8u4ie7.js → it-C9g0xD6S.js} +1 -1
- package/{web/dist/assets/mpegts-DsEoUEPH.js → backtoschool/dist/assets/mpegts-GAwbg-pX.js} +1 -1
- package/{web/dist/assets/mpegts-LO6RVLD6-CC8jMmPy.js → backtoschool/dist/assets/mpegts-LO6RVLD6-BrVQzFhM.js} +1 -1
- package/backtoschool/dist/assets/native-C7JTKWJH-BUyIoj0P.js +1 -0
- package/{web/dist/assets/nl-BU0Mn-e-.js → backtoschool/dist/assets/nl-Ciq1Yrk4.js} +1 -1
- package/{web/dist/assets/ru-ClqNCOTW.js → backtoschool/dist/assets/ru-B_ZMUvh6.js} +1 -1
- package/backtoschool/dist/assets/{sv-CV2-POKP.js → sv-DH0ZO3Eh.js} +1 -1
- package/{web/dist/assets/uk-K5yQBF0h.js → backtoschool/dist/assets/uk-Cof-TUZd.js} +1 -1
- package/backtoschool/dist/assets/{vi-BDZew-O9.js → vi-D0QPpzbE.js} +1 -1
- package/{web/dist/assets/zh-a2v2x-3e.js → backtoschool/dist/assets/zh-CLTzTBOU.js} +1 -1
- package/backtoschool/dist/index.html +61 -10
- package/dist/classroom.d.ts +1 -1
- package/dist/classroom.js +4 -0
- package/dist/live-api.d.ts +10 -0
- package/dist/live-api.js +8 -0
- package/dist/live-events.js +1 -1
- package/dist/live-voice.d.ts +3 -0
- package/dist/live-voice.js +27 -4
- package/dist/locales/ar.d.ts +15 -0
- package/dist/locales/cs.d.ts +15 -0
- package/dist/locales/da.d.ts +15 -0
- package/dist/locales/de.d.ts +15 -0
- package/dist/locales/en.d.ts +15 -0
- package/dist/locales/es.d.ts +15 -0
- package/dist/locales/fi.d.ts +15 -0
- package/dist/locales/fr.d.ts +15 -0
- package/dist/locales/hi.d.ts +15 -0
- package/dist/locales/hu.d.ts +15 -0
- package/dist/locales/id.d.ts +15 -0
- package/dist/locales/it.d.ts +15 -0
- package/dist/locales/nl.d.ts +15 -0
- package/dist/locales/platforms.d.ts +19 -0
- package/dist/locales/platforms.js +19 -0
- package/dist/locales/ru.d.ts +15 -0
- package/dist/locales/sv.d.ts +15 -0
- package/dist/locales/uk.d.ts +15 -0
- package/dist/locales/vi.d.ts +15 -0
- package/dist/locales/zh.d.ts +15 -0
- package/dist/nixamp-link-api.d.ts +44 -0
- package/dist/nixamp-link-api.js +190 -0
- package/dist/nixamp-link-types.d.ts +33 -0
- package/dist/nixamp-link-types.js +5 -0
- package/dist/nixamp-link.d.ts +66 -0
- package/dist/nixamp-link.js +231 -0
- package/dist/notify.d.ts +6 -4
- package/dist/notify.js +14 -25
- package/dist/oauth-api.d.ts +1 -1
- package/dist/oauth-api.js +27 -9
- package/dist/oauth-server.d.ts +9 -1
- package/dist/oauth-server.js +24 -2
- package/dist/profiles.d.ts +85 -0
- package/dist/profiles.js +0 -0
- package/dist/server.d.ts +12 -2
- package/dist/server.js +205 -13
- package/dist/voice-provider.d.ts +9 -0
- package/dist/voice-provider.js +27 -0
- package/dist/watch-party.d.ts +8 -0
- package/dist/watch-party.js +21 -0
- package/package.json +6 -6
- package/src/classroom.ts +5 -1
- package/src/live-api.ts +13 -0
- package/src/live-events.ts +1 -1
- package/src/live-voice.ts +25 -3
- package/src/locales/platforms.ts +21 -0
- package/src/nixamp-link-api.ts +220 -0
- package/src/nixamp-link-types.ts +36 -0
- package/src/nixamp-link.ts +265 -0
- package/src/notify.ts +19 -34
- package/src/oauth-api.ts +30 -11
- package/src/oauth-server.ts +24 -2
- package/src/profiles.ts +0 -0
- package/src/server.ts +192 -15
- package/src/voice-provider.ts +22 -0
- package/src/watch-party.ts +23 -0
- package/web/dist/assets/{ar-DhdXPO3p.js → ar-BqLaLSMR.js} +1 -1
- package/web/dist/assets/{cs-CoTzYnZt.js → cs-CfoQJwKM.js} +1 -1
- package/{backtoschool/dist/assets/da-DueRd5zz.js → web/dist/assets/da-8MmH23fh.js} +1 -1
- package/{backtoschool/dist/assets/de-DIG6WxUZ.js → web/dist/assets/de-Brry3OMh.js} +1 -1
- package/web/dist/assets/{es-BMGb7XlT.js → es-CGxJs7b8.js} +1 -1
- package/web/dist/assets/{fi-CXNsmIrh.js → fi-BDAAZtto.js} +1 -1
- package/web/dist/assets/{fr-BpvyrESQ.js → fr-9sxYL0Qy.js} +1 -1
- package/{backtoschool/dist/assets/hi-CGlN72JQ.js → web/dist/assets/hi-Cc7ZsdL7.js} +1 -1
- package/web/dist/assets/hls-3VKVEQE3-Dx7qltzA.js +1 -0
- package/web/dist/assets/{hu-CosB3vlS.js → hu-CvB9aIyN.js} +1 -1
- package/web/dist/assets/{id-DNumDlwq.js → id-Bmrh06Hw.js} +1 -1
- package/web/dist/assets/index-BQuoiKg9.js +3 -0
- package/web/dist/assets/{index-jLCo7PIA.css → index-Bo3utcDw.css} +1 -1
- package/web/dist/assets/{it-IJKhyCGw.js → it-SbaxFUIP.js} +1 -1
- package/web/dist/assets/mpegts-BdwONu8t.js +3 -0
- package/web/dist/assets/mpegts-LO6RVLD6-CqW3DT1n.js +1 -0
- package/{backtoschool/dist/assets/nl-CnYXq0K4.js → web/dist/assets/nl-CqimSo3B.js} +1 -1
- package/{backtoschool/dist/assets/ru-BatrUfYu.js → web/dist/assets/ru-wIfpMpU9.js} +1 -1
- package/web/dist/assets/{sv-Df_aXTD6.js → sv-BAyIUHP5.js} +1 -1
- package/{backtoschool/dist/assets/uk-vLtqKpHm.js → web/dist/assets/uk-D2jFJm6l.js} +1 -1
- package/web/dist/assets/{vi-CYfcOUeA.js → vi-BdH3SLlR.js} +1 -1
- package/{backtoschool/dist/assets/zh-C9hBmQKA.js → web/dist/assets/zh-5xz5Agt-.js} +1 -1
- package/web/dist/index.html +33 -2
- package/web/dist/sw.js +23 -23
- package/backtoschool/dist/assets/index-CP4oTs6H.css +0 -1
- package/backtoschool/dist/assets/index-DDGO_FOw.js +0 -113
- package/web/dist/assets/index-CY3lAwM2.js +0 -3
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={"Supported platforms":`Supported platforms`,"In review":`In review`,"Not available":`Not available`,"Install PWA":`Install PWA`,"PWA installed":`PWA installed`,"Web app":`Web app`,"Install the web app":`Install the web app`,"Keep BackToSchool on your home screen or desktop. No app store needed.":`Keep BackToSchool on your home screen or desktop. No app store needed.`,"iPhone or iPad: open this site in Safari, tap Share, then Add to Home Screen.":`iPhone or iPad: open this site in Safari, tap Share, then Add to Home Screen.`,"Android: open your browser menu and choose Install app or Add to Home screen.":`Android: open your browser menu and choose Install app or Add to Home screen.`,"Desktop: look for Install in the address bar or browser menu. The option depends on your browser.":`Desktop: look for Install in the address bar or browser menu. The option depends on your browser.`,"You can also keep using BackToSchool in this browser.":`You can also keep using BackToSchool in this browser.`,"The web app is installed. You can keep learning here.":`The web app is installed. You can keep learning here.`,"Continue learning":`Continue learning`,"The install prompt could not open. Select Web app again for installation instructions.":`The install prompt could not open. Select Web app again for installation instructions.`,"Follow host":`Follow host`,Following:`Following`,"You’ll get email and web notifications for this host.":`You’ll get email and web notifications for this host.`,"Notifications turned off for this host.":`Notifications turned off for this host.`,"Could not update notifications.":`Could not update notifications.`},t={...e,"No parties live right now.":`No parties live right now.`,"Could not refresh parties.":`Could not refresh parties.`,"Pick a server in the directory, or paste its link here.":`Pick a server in the directory, or paste its link here.`,"Interface language":`Interface language`,Language:`Language`,"Translation language":`Translation language`,"Original (auto-detect)":`Original (auto-detect)`,Play:`Play`,Pause:`Pause`,Stop:`Stop`,Next:`Next`,Previous:`Previous`,Select:`Select`,"Next/Prev":`Next/Prev`,Quit:`Quit`,"Now Playing":`Now Playing`,"Spectrum Analyser":`Spectrum Analyser`,Playlist:`Playlist`,Files:`Files`,"Open files":`Open files`,"Open folder":`Open folder`,"Add to library":`Add to library`,"Replace playlist":`Replace playlist`,Filter:`Filter`,Search:`Search`,"Nothing loaded.":`Nothing loaded.`,"Empty.":`Empty.`,"Loading…":`Loading…`,"Connecting…":`Connecting…`,Connected:`Connected`,"Not connected":`Not connected`,"No source":`No source`,Playing:`Playing`,Stopped:`Stopped`,Volume:`Volume`,Seek:`Seek`,"Full screen":`Full screen`,Download:`Download`,Share:`Share`,Copy:`Copy`,"Copy link":`Copy link`,Copied:`Copied`,Save:`Save`,Cancel:`Cancel`,Close:`Close`,Remove:`Remove`,Delete:`Delete`,Edit:`Edit`,Add:`Add`,Send:`Send`,Retry:`Retry`,Back:`Back`,"Next page":`Next page`,"Previous page":`Previous page`,"Show more":`Show more`,Panels:`Panels`,"Reset layout":`Reset layout`,Show:`Show`,Hide:`Hide`,Collapse:`Collapse`,Expand:`Expand`,"Move up":`Move up`,"Move down":`Move down`,Install:`Install`,"TV mode":`TV mode`,On:`On`,Off:`Off`,Account:`Account`,"Sign in":`Sign in`,"Sign out":`Sign out`,"Create account":`Create account`,Email:`Email`,Password:`Password`,"Forgot password?":`Forgot password?`,"Welcome back":`Welcome back`,Profile:`Profile`,Handle:`Handle`,"Your servers":`Your servers`,Server:`Server`,Connect:`Connect`,Disconnect:`Disconnect`,Directory:`Directory`,Favourites:`Favourites`,Follow:`Follow`,Unfollow:`Unfollow`,Notifications:`Notifications`,"Phone number":`Phone number`,"Save number":`Save number`,Transcript:`Transcript`,Captions:`Captions`,"Translate audio":`Translate audio`,"Audio language":`Audio language`,"Audio options":`Audio options`,"Keep background sound":`Keep background sound`,"Background level":`Background level`,"Speaker voices":`Speaker voices`,"Any voice":`Any voice`,"Male voice":`Male voice`,"Female voice":`Female voice`,"Original audio.":`Original audio.`,"Buy translated audio":`Buy translated audio`,"Audio credit":`Audio credit`,"Buy pass":`Buy pass`,Pass:`Pass`,"Pay with":`Pay with`,"Check payment":`Check payment`,"Open checkout":`Open checkout`,"Free sessions":`Free sessions`,"Usage rates and expiry":`Usage rates and expiry`,Catalogs:`Catalogs`,"Add catalog":`Add catalog`,"Catalog name":`Catalog name`,Link:`Link`,"Play link":`Play link`,"Go live":`Go live`,Publish:`Publish`,Listen:`Listen`,"Live now":`Live now`,Upcoming:`Upcoming`,Parties:`Parties`,"Join party":`Join party`,"Invite code":`Invite code`,Invite:`Invite`,Chat:`Chat`,"Chat message":`Chat message`,People:`People`,Speaker:`Speaker`,Speakers:`Speakers`,Listener:`Listener`,Moderator:`Moderator`,"Raise hand":`Raise hand`,"Hand raises":`Hand raises`,Questions:`Questions`,Resources:`Resources`,Replay:`Replay`,Schedule:`Schedule`,Event:`Event`,Host:`Host`,About:`About`,Stage:`Stage`,Title:`Title`,Description:`Description`,Topic:`Topic`,Public:`Public`,"Anyone with the link":`Anyone with the link`,"Invited people":`Invited people`,"Who can join":`Who can join`,"Date and time":`Date and time`,"Expected length":`Expected length`,Repeat:`Repeat`,"Does not repeat":`Does not repeat`,"Every day":`Every day`,"Every week":`Every week`,Homepage:`Homepage`,"Host name":`Host name`,"Profile photo URL":`Profile photo URL`,"Broadcast link":`Broadcast link`,"Edit event":`Edit event`,"Save changes":`Save changes`,"Create live":`Create live`,"Schedule class":`Schedule class`,"Start class":`Start class`,"End event":`End event`,"End session":`End session`,"Session ended":`Session ended`,"Event ended":`Event ended`,Cancelled:`Cancelled`,"Replay available":`Replay available`,Join:`Join`,"Create invite":`Create invite`,"Invite as":`Invite as`,"Watch now":`Watch now`,"Start a room":`Start a room`,"Recent replays":`Recent replays`,"Your account":`Your account`,"Write with AI":`Write with AI`,"Suggested title":`Suggested title`,"Suggested description":`Suggested description`,"Suggested topic":`Suggested topic`,"Use these details":`Use these details`,"Learn something live.":`Learn something live.`,"Screen share":`Screen share`,"Upload and broadcast":`Upload and broadcast`,Help:`Help`,"Reload Player":`Reload Player`,"Copy Bundled CLI Path":`Copy Bundled CLI Path`,"Developer tools":`Developer tools`,Undo:`Undo`,Redo:`Redo`,Cut:`Cut`,Paste:`Paste`,"Select all":`Select all`,Status:`Status`,"Activity log":`Activity log`,Admin:`Admin`,"Playback controls":`Playback controls`,"Tracks and folders":`Tracks and folders`,"Original-language captions.":`Original-language captions.`,"Skip to playback controls":`Skip to playback controls`,"Skip to playlist":`Skip to playlist`,"Skip to transcript and translated audio":`Skip to transcript and translated audio`},n={"■ STOPPED":`Stopped`,"▶ PLAYING":`Playing`,LOADING:`Loading…`,"no source":`No source`,"not connected":`Not connected`,"Now playing":`Now Playing`,"● GO LIVE":`Go live`,"● Go live":`Go live`,"⤓ Download":`Download`,"A man's voice":`Male voice`,"A woman's voice":`Female voice`,"Catalogs on this server":`Catalogs`,"Catalog folders":`Catalogs`,"Parties on this server":`Parties`,"Servers streaming now":`Directory`,"Playlist (0)":`Playlist`,"Playlist folders":`Playlist`,"Playlist pages":`Playlist`,"Filter these files":`Filter`,"Filter these entries":`Filter`,"Filter the entries":`Filter`,"Filter the playlist":`Filter`,"Create a free account":`Create account`,"Create one":`Create account`,"Create your account":`Create account`,"New here? Create an account":`Create account`,"Already have an account? Sign in":`Sign in`,"Your NixAmp account":`Your account`,"Your public handle":`Handle`,handle:`Handle`,password:`Password`,"Phone number for texts":`Phone number`,"Back to the player":`Back`,"Share what is playing":`Share`,"Share this stream":`Share`,"Link to this stream":`Link`,"Copy this stream's URL":`Copy link`,"A link to play":`Link`,"A server's link":`Server`,"Close translated audio purchase":`Close`,"Open secure checkout ↗ (new tab)":`Open checkout`,"Checking…":`Loading…`,"Browse the directory":`Directory`,"See what is live":`Live now`,"Join live":`Join`,"Raise Hand":`Raise hand`,"Hand Raises":`Hand raises`,"Hide this":`Hide`,Log:`Activity log`,"Status:":`Status`,"Nixamp player":`Playback controls`,"Nixamp audio and video player":`Playback controls`,"What is being said":`Transcript`,"The room's chat":`Chat`,Trollbox:`Chat`,"A line for the trollbox":`Chat message`,"Say something to the room…":`Chat message`,"Send it":`Send`,"Something to add":`Chat message`,"What to call it":`Catalog name`,"call it something":`Catalog name`,"An m3u catalog to add":`Catalogs`,"On this device":`Play`,"Play on this device":`Play`,"What this is":`About`,"Looking for servers…":`Loading…`,"Finding today’s conversations…":`Loading…`,"Coming up":`Upcoming`,"Listen after class":`Replay`,"Schedule live":`Schedule class`,"Schedule a class":`Schedule class`,"Plan a conversation":`Schedule class`,"Your classroom":`Event`,"Join in":`Join`,"Open a room →":`Start a room`,"Chat message":`Chat message`,"Add to the conversation":`Chat message`,"Create live":`Create live`,"Host stage":`Stage`,"Your host":`Host`,"Class host":`Host`,"Hand raised ✓":`Raise hand`,"Copied ✓":`Copied`,"Screen share with Pairux ↗":`Screen share`,"Upload & broadcast in Nixamp ↗":`Upload and broadcast`,"Open Music Folder…":`Open folder`,"Choose a music folder":`Open folder`,"Main navigation":`Panels`,"Skip to a section":`Panels`},r=[{code:`en`,label:`English`},{code:`de`,label:`Deutsch`},{code:`sv`,label:`Svenska`},{code:`es`,label:`Español`},{code:`fr`,label:`Français`},{code:`it`,label:`Italiano`},{code:`nl`,label:`Nederlands`},{code:`da`,label:`Dansk`},{code:`fi`,label:`Suomi`},{code:`ru`,label:`Русский`},{code:`uk`,label:`Українська`},{code:`cs`,label:`Čeština`},{code:`hu`,label:`Magyar`},{code:`zh`,label:`中文`},{code:`ar`,label:`العربية`},{code:`hi`,label:`हिन्दी`},{code:`vi`,label:`Tiếng Việt`},{code:`id`,label:`Bahasa Indonesia`}],i=`nixamp.ui.language`;function a(e){let t=typeof e==`string`?e.trim().toLowerCase().split(/[-_.@]/)[0]:``;return r.find(e=>e.code===t)?.code??`en`}function o(e,t=[]){let n=e=>{let t=typeof e==`string`?e.trim().toLowerCase().split(/[-_.@]/)[0]:``;return r.find(e=>e.code===t)?.code};return n(e)??t.map(n).find(Boolean)??`en`}var s=`modulepreload`,c=function(e){return`/`+e},l={},u=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function u(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=c(t,n),t=u(t),t in l)return;l[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:s,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},d={en:async()=>({default:t}),de:()=>u(()=>import(`./de-DIG6WxUZ.js`),[]),sv:()=>u(()=>import(`./sv-CV2-POKP.js`),[]),es:()=>u(()=>import(`./es-BwQQh_C8.js`),[]),fr:()=>u(()=>import(`./fr-DNekMW0h.js`),[]),it:()=>u(()=>import(`./it-jO8u4ie7.js`),[]),nl:()=>u(()=>import(`./nl-CnYXq0K4.js`),[]),da:()=>u(()=>import(`./da-DueRd5zz.js`),[]),fi:()=>u(()=>import(`./fi-DKPYMsbo.js`),[]),ru:()=>u(()=>import(`./ru-BatrUfYu.js`),[]),uk:()=>u(()=>import(`./uk-vLtqKpHm.js`),[]),cs:()=>u(()=>import(`./cs-BiiJOLTm.js`),[]),hu:()=>u(()=>import(`./hu-gcw9ouWH.js`),[]),zh:()=>u(()=>import(`./zh-C9hBmQKA.js`),[]),ar:()=>u(()=>import(`./ar-CmpEhms8.js`),[]),hi:()=>u(()=>import(`./hi-CGlN72JQ.js`),[]),vi:()=>u(()=>import(`./vi-BDZew-O9.js`),[]),id:()=>u(()=>import(`./id-Bz51zxz6.js`),[])},f=new class{load;code=`en`;get language(){return this.code}constructor(e=async e=>(await d[e]()).default){this.load=e}messages=t;revision=0;numberFormats=new Map;dateFormats=new Map;listeners=new Set;async setLanguage(e){let t=++this.revision,n=a(e),r=await this.load(n);if(t!==this.revision)return!1;this.code=n,this.messages=r,this.numberFormats.clear(),this.dateFormats.clear();for(let e of this.listeners)e();return!0}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}text(e,t={}){let r=this.language!==`en`&&Object.hasOwn(n,e)?n[e]:e,i=Object.hasOwn(this.messages,r)?this.messages[r]:e;return this.language!==`en`&&Object.hasOwn(n,e)&&(i=(e.match(/^[▶■●⤓]\s+/)?.[0]??``)+i+(e.endsWith(` ✓`)?` ✓`:``)),i.replace(/\{([\w]+)\}/g,(e,n)=>Object.hasOwn(t,n)?String(t[n]):e)}number(e,t){let n=JSON.stringify(t??{}),r=this.numberFormats.get(n);return r||(this.numberFormats.size>=64&&this.numberFormats.clear(),r=new Intl.NumberFormat(this.language,t),this.numberFormats.set(n,r)),r.format(e)}date(e,t){let n=JSON.stringify(t??{}),r=this.dateFormats.get(n);return r||(this.dateFormats.size>=64&&this.dateFormats.clear(),r=new Intl.DateTimeFormat(this.language,t),this.dateFormats.set(n,r)),r.format(e)}get direction(){return this.language===`ar`?`rtl`:`ltr`}},p=(e,t)=>f.text(e,t),m=new Map;function h(e,t,n){let r=m.get(e);r||(r=new Map,m.set(e,r)),r.set(t,n),n()}function g(e,t){e instanceof Element&&e.removeAttribute(`data-i18n`);let n=``,r;return h(e,`text`,()=>{if(r!==void 0&&e.textContent!==r){m.get(e)?.delete(`text`);return}n=t()??``,r=n,e.textContent!==n&&(e.textContent=n)}),n}var ee=[`aria-label`,`title`,`placeholder`,`data-title`],te=[`[data-i18n]`,...ee.map(e=>`[data-i18n-${e}]`)].join(`,`);function ne(e){let t=[...e.querySelectorAll(te)];e instanceof HTMLElement&&e.matches(te)&&t.unshift(e);for(let e of t){if(e.closest(`[translate="no"], [contenteditable="true"]`))continue;let t=e.getAttribute(`data-i18n`);if(t){let n=e.textContent;h(e,`text`,()=>{if(e.textContent!==n){m.get(e)?.delete(`text`),e.removeAttribute(`data-i18n`);return}n=p(t),e.textContent!==n&&(e.textContent=n)})}for(let t of ee){let n=e.getAttribute(`data-i18n-${t}`);if(n){let r=e.getAttribute(t);h(e,t,()=>{if(e.getAttribute(t)!==r){m.get(e)?.delete(t),e.removeAttribute(`data-i18n-${t}`);return}r=p(n),e.getAttribute(t)!==r&&e.setAttribute(t,r)})}}}}function _(){document.documentElement.lang=f.language,document.documentElement.dir=f.direction;for(let[e,t]of m){if(!e.isConnected){m.delete(e);continue}for(let e of t.values())e()}for(let e of document.querySelectorAll(`[data-ui-language]`))e.value=f.language}var re=0;async function ie(e){let t=++re;try{if(!await f.setLanguage(e)||t!==re)return;try{localStorage.setItem(i,f.language)}catch{}window.nixampLanguage?.set(f.language).catch(()=>{})}catch{_()}}async function ae(){let e=o(null,navigator.languages);try{e=o(await window.nixampLanguage?.get()??localStorage.getItem(`nixamp.ui.language`),navigator.languages)}catch{}for(let e of document.querySelectorAll(`[data-ui-language]`))e.replaceChildren(...r.map(e=>{let t=new Option(e.label,e.code);return t.lang=e.code,t.dir=`auto`,t})),e.addEventListener(`change`,()=>{ie(e.value)});ne(document),_(),f.onChange(_),new MutationObserver(e=>{for(let t of e)for(let e of t.addedNodes)e instanceof Element&&ne(e);for(let e of m.keys())e.isConnected||m.delete(e)}).observe(document.body,{childList:!0,subtree:!0}),window.addEventListener(`storage`,e=>{e.key===`nixamp.ui.language`&&f.setLanguage(o(e.newValue,navigator.languages)).catch(()=>{})}),window.nixampLanguage?.subscribe(e=>{e!==f.language&&f.setLanguage(e).catch(()=>{})});try{await f.setLanguage(e)}catch{}}var v=null,y=!1,b=window.matchMedia(`(display-mode: standalone)`).matches||!!navigator.standalone;window.addEventListener(`beforeinstallprompt`,e=>{e.preventDefault(),v=e}),window.addEventListener(`appinstalled`,()=>{b=!0,v=null;let e=document.querySelector(`[data-pwa-label]`);e&&g(e,()=>p(`PWA installed`))});function oe(){let e=b?`PWA installed`:`Install PWA`;return`<div class="platforms" role="group" aria-label="Supported platforms" data-i18n-aria-label="Supported platforms">
|
|
2
|
-
<div class="platform-badges">
|
|
3
|
-
<div class="platform-badge platform-fire-tv">
|
|
4
|
-
<img src="/platform-icons/amazon.svg" width="28" height="28" alt="" />
|
|
5
|
-
<span><small data-i18n="In review">In review</small><strong>Amazon Fire TV</strong><small>Fire TV Stick</small></span>
|
|
6
|
-
</div>
|
|
7
|
-
<button class="platform-badge platform-pwa" type="button" data-install-pwa>
|
|
8
|
-
<img src="/platform-icons/pwa.svg" width="40" height="40" alt="" />
|
|
9
|
-
<span><small data-pwa-label data-i18n="${e}">${e}</small><strong data-i18n="Web app">Web app</strong></span>
|
|
10
|
-
</button>
|
|
11
|
-
<button class="platform-badge platform-unavailable" type="button" disabled>
|
|
12
|
-
<img src="/platform-icons/apple.svg" width="28" height="28" alt="" />
|
|
13
|
-
<span><small data-i18n="Not available">Not available</small><strong>App Store</strong></span>
|
|
14
|
-
</button>
|
|
15
|
-
<button class="platform-badge platform-unavailable" type="button" disabled>
|
|
16
|
-
<img src="/platform-icons/google-play.svg" width="28" height="28" alt="" />
|
|
17
|
-
<span><small data-i18n="Not available">Not available</small><strong>Google Play</strong></span>
|
|
18
|
-
</button>
|
|
19
|
-
</div>
|
|
20
|
-
</div>`}function se(){let e=document.querySelector(`#pwa-dialog`);e.querySelector(`[data-pwa-instructions]`).hidden=b,e.querySelector(`[data-pwa-installed]`).hidden=!b,e.open||e.showModal()}document.addEventListener(`click`,e=>{let t=e.target.closest(`[data-install-pwa]`);if(!t||y)return;if(b||!v){se();return}let n=v;v=null,y=!0,t.setAttribute(`aria-busy`,`true`),n.prompt().catch(()=>{let e=document.querySelector(`#pwa-status`);e&&g(e,()=>p(`The install prompt could not open. Select Web app again for installation instructions.`))}).finally(()=>{y=!1,t.removeAttribute(`aria-busy`)})}),document.querySelector(`#pwa-dialog`).addEventListener(`close`,()=>{document.querySelector(`[data-install-pwa]`)?.focus({preventScroll:!0})});var x=class extends Error{status;constructor(e,t){super(e),this.status=t}};async function S(e,t={}){let n=await fetch(e,{credentials:`same-origin`,...t,headers:{...t.body?{"content-type":`application/json`}:{},...t.headers}}),r={};try{r=await n.json()}catch{r={}}if(!n.ok)throw new x(String((r&&typeof r==`object`?r:{}).error??`That did not work.`),n.status);return r}function C(e,t,n=`POST`){return S(e,{method:n,body:JSON.stringify(t)})}function ce(e,t,n){let r=e.querySelector(`#event-ai-write`),i=e.querySelector(`#event-ai-cancel`),a=e.querySelector(`#event-ai-apply`),o=e.querySelector(`#event-ai-preview`),s=e.querySelector(`#event-ai-status`),c={title:e.querySelector(`#event-ai-title`),description:e.querySelector(`#event-ai-description`),topic:e.querySelector(`#event-ai-topic`)},l=null,u=null,d=null,f=t=>e.elements.namedItem(t).value,m=()=>({title:f(`title`),description:f(`description`),topic:f(`topic`),hostName:f(`hostName`),startsAt:f(`startsAt`),timezone:n(),duration:f(`expectedDurationMinutes`),recurrence:f(`recurrence`)});function h(){l?.abort(),l=null,u=null,d=null,o.hidden=!0,o.removeAttribute(`aria-busy`),i.hidden=!0,g(r,()=>p(`Write with AI`)),r.removeAttribute(`aria-disabled`),g(a,()=>p(`Use these details`)),a.setAttribute(`aria-disabled`,`true`),s.textContent=``;for(let e of Object.values(c))e.value=``}return r.addEventListener(`click`,async()=>{if(l||e.getAttribute(`aria-busy`)===`true`)return;let n=m();if(![n.title,n.description,n.topic].some(e=>e.trim())){s.textContent=`Add a title, description, or topic first. Your words become the prompt.`;return}let f=new AbortController;l=f,d=n,u=null,r.setAttribute(`aria-disabled`,`true`),r.textContent=`Writing…`,i.hidden=!1,g(i,()=>p(`Cancel`)),o.hidden=!1,o.setAttribute(`aria-busy`,`true`),g(a,()=>p(`Use these details`)),a.setAttribute(`aria-disabled`,`true`);for(let e of Object.values(c))e.value=``;s.textContent=`Writing a draft from your event details… You can keep editing.`;try{let e=await S(`/api/v1/events/ai-draft`,{method:`POST`,body:JSON.stringify(n),signal:f.signal});if(l!==f||!t.open)return;u=e.draft;for(let e of[`title`,`description`,`topic`])c[e].value=u[e];a.removeAttribute(`aria-disabled`),s.textContent=`Draft ready. Review it below, then use these details if you like them.`}catch(e){if(l!==f||f.signal.aborted)return;s.textContent=e instanceof Error?e.message:`Could not write a draft. Your text is unchanged.`}finally{l===f&&(l=null,o.removeAttribute(`aria-busy`),r.removeAttribute(`aria-disabled`),r.textContent=`Write again`,i.textContent=`Discard draft`)}}),i.addEventListener(`click`,()=>{let e=!!l;h(),s.textContent=e?`Draft cancelled. Your text is unchanged.`:`Draft discarded. Your text is unchanged.`,i.hidden=!1,i.textContent=`Dismiss`}),a.addEventListener(`click`,()=>{if(u&&d&&!l&&a.getAttribute(`aria-disabled`)!==`true`){if(JSON.stringify(m())!==JSON.stringify(d)){s.textContent=`Your inputs changed while this draft was being written. Click Write again to include those edits, or copy text from the preview.`;return}for(let t of[`title`,`description`,`topic`])e.elements.namedItem(t).value=u[t];a.setAttribute(`aria-disabled`,`true`),a.textContent=`Details applied`,s.textContent=`Draft applied to your form. Review your event and save when you’re ready.`}}),t.addEventListener(`close`,h),e.addEventListener(`submit`,()=>{l&&h()}),{reset:h}}function w(e){if(typeof e!=`string`||e.length>2048)return null;try{let t=new URL(e);return t.protocol!==`https:`||t.username||t.password?null:t.href}catch{return null}}function le(e){let t=w(e);if(!t)return null;let n=new URL(t);if(!n.port&&(n.hostname===`pairux.com`||n.hostname===`www.pairux.com`)){let e=/^\/(?:l|join|embed)\/([A-Za-z0-9_-]{1,64})\/?$/.exec(n.pathname)?.[1];return e?{provider:`pairux`,url:`https://pairux.com/l/${e}`,embed:`https://pairux.com/embed/${e}`,join:`https://pairux.com/join/${e}`}:null}if(!n.port&&(n.hostname===`nixamp.com`||n.hostname===`www.nixamp.com`)){if(n.pathname!==`/`)return null;let e=n.searchParams.get(`url`)||``,t=n.searchParams.get(`play`)||(e?`live`:``);if(/\/admin\//i.test(e)||/\/admin\//i.test(t)||n.searchParams.has(`key`)||e&&!w(e)||!/^(?:live|channel:[^\s]+|track:\d+)$/.test(t)&&!w(t))return null;let r=new URL(`https://nixamp.com/`);e&&r.searchParams.set(`url`,e),r.searchParams.set(`play`,t);let i=r.href;return r.searchParams.set(`embed`,`1`),{provider:`nixamp`,url:i,embed:r.href,join:i}}if(n.hostname.endsWith(`.nixamp.com`)&&/^\/view\/[A-Za-z0-9_-]+\/?$/.test(n.pathname)&&!n.search){let e=new URL(`https://nixamp.com/`);return e.searchParams.set(`url`,n.href),e.searchParams.set(`play`,`live`),le(e.href)}return null}ae();var T=document.querySelector(`#main`),E=document.querySelector(`#account-button`),D=document.querySelector(`#account-dialog`),O=document.querySelector(`#account-form`),ue=document.querySelector(`#account-title`),de=document.querySelector(`#account-copy`),k=document.querySelector(`#account-error`),fe=document.querySelector(`#account-mode`),A=document.querySelector(`#event-dialog`),j=document.querySelector(`#event-form`),pe=document.querySelector(`#event-form-title`),me=document.querySelector(`#event-kicker`),M=document.querySelector(`#event-submit`),N=document.querySelector(`#event-error`),P=document.querySelector(`#schedule-fields`),F=null,I=!1,L=!1,R=null,z=!1,B=null,V=null,H=null,he=ce(j,A,()=>R?.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone??`UTC`),ge=new WeakMap;`serviceWorker`in navigator&&location.protocol===`https:`&&navigator.serviceWorker.register(`/sw.js`).catch(()=>{});function _e(e){let t=atob((e+`=`.repeat((4-e.length%4)%4)).replace(/-/g,`+`).replace(/_/g,`/`)),n=new Uint8Array(new ArrayBuffer(t.length));for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}async function ve(){if(`serviceWorker`in navigator&&`PushManager`in window&&`Notification`in window&&(Notification.permission!=="default"||await Notification.requestPermission()===`granted`)&&Notification.permission===`granted`)try{let e=await navigator.serviceWorker.ready,{publicKey:t}=await(await fetch(`/api/v1/notify/key`)).json();if(!t)return;let n=await e.pushManager.getSubscription()??await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:_e(t)});await fetch(`/api/v1/notify/subscribe`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n.toJSON())})}catch{}}function ye(e,t){ge.get(e)===t||e.contains(document.activeElement)||(e.innerHTML=t,ge.set(e,t))}function U(e){return String(e??``).replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}function be(e){let t=document.querySelector(`#event-update`);t&&t.textContent!==e&&(t.textContent=e),document.querySelector(`.class-update`)?.removeAttribute(`hidden`)}function W(e){return`/live/${encodeURIComponent(e.slug)}`}function G(){let e=new URLSearchParams(location.search).get(`invite`);return e?`?invite=${encodeURIComponent(e)}`:``}function K(e,t={}){return e?new Intl.DateTimeFormat(f.language,{weekday:`short`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,...t}).format(new Date(e)):`Time to be announced`}function q(e){return e.status===`live`?p(`Live now`):e.status===`ended`?e.recordingId?p(`Replay available`):p(`Event ended`):e.status===`cancelled`?p(`Cancelled`):K(e.startsAt)}function xe(e){return H?.permissions.includes(e)??!1}function J(){g(E,()=>F?F.email.split(`@`)[0]||p(`Account`):p(`Sign in`)),E.classList.toggle(`signed-in`,!!F)}async function Se(){try{F=(await S(`/api/v1/auth/me`)).account}catch{F=null}J()}function Y(e){if(F){D.showModal(),ue.textContent=`Signed in as ${F.email}`,de.textContent=`Your BackToSchool identity is your NixAmp account.`,O.hidden=!0;return}B=e??null,O.hidden=!1,k.textContent=``,Ce(),D.showModal()}function Ce(){g(ue,()=>p(I?`Create your account`:`Welcome back`)),de.textContent=I?`One NixAmp account works here and everywhere NixAmp goes.`:`Sign in to host, chat, or raise your hand.`,g(fe,()=>p(I?`Already have an account? Sign in`:`New here? Create an account`)),document.querySelector(`#account-forgot`).hidden=I;let e=O.elements.namedItem(`password`);e.autocomplete=I?`new-password`:`current-password`,g(O.querySelector(`button[type="submit"]`),()=>p(I?`Create account`:`Sign in`))}function X(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}T${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`}function Z(e,t=null){if(!F){Y(()=>Z(e,t));return}if(z)return;R=t,he.reset(),j.reset(),L=e===`scheduled`,P.hidden=!L,g(pe,()=>p(t?`Edit event`:L?`Schedule a class`:`Go live`)),g(me,()=>t?p(`Your classroom`):`Teach something live`),g(M,()=>p(t?`Save changes`:L?`Schedule class`:`Create live`)),N.textContent=``;let n=j.elements.namedItem(`startsAt`);if(n.required=L&&(!t||!!t.startsAt),t){for(let e of[`title`,`description`,`topic`,`visibility`,`broadcastUrl`,`hostName`,`homepageUrl`,`avatarUrl`,`recurrence`])j.elements.namedItem(e).value=t[e]??(e===`recurrence`?`none`:``);for(let e of[`chatEnabled`,`handRaiseEnabled`])j.elements.namedItem(e).checked=t[e];t.startsAt&&(n.value=X(t.startsAt));let e=j.elements.namedItem(`expectedDurationMinutes`),r=String(t.expectedDurationMinutes??60);[...e.options].some(e=>e.value===r)||e.add(new Option(`${r} minutes`,r)),e.value=r}else if(L){let e=new Date(Date.now()+36e5);e.setMinutes(Math.ceil(e.getMinutes()/15)*15,0,0),n.value=X(e.toISOString())}let r=Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`;document.querySelector(`#schedule-timezone`).textContent=`Date and time are shown in ${r}.`+(t?.recurrence?` This class repeats in ${t.timezone}.`:``),A.showModal()}function Q(e){history.pushState(null,``,e),$()}function we(e){let t=e.status===`live`||e.status===`starting`;return`
|
|
21
|
-
<article class="event-card ${t?`is-live`:``}">
|
|
22
|
-
<a href="${W(e)}" data-link>
|
|
23
|
-
<div class="event-card-top">
|
|
24
|
-
<span class="status-pill ${t?`status-live`:``}">${t?`Live`:U(q(e))}</span>
|
|
25
|
-
${e.topic?`<span class="topic">${U(e.topic)}</span>`:``}
|
|
26
|
-
</div>
|
|
27
|
-
<h3>${U(e.title)}</h3>
|
|
28
|
-
<p>${U(e.description||`Drop in and learn something with us.`)}</p>
|
|
29
|
-
<span class="event-link">${t?`Watch live`:`See event`}<span aria-hidden="true">→</span></span>
|
|
30
|
-
</a>
|
|
31
|
-
</article>`}async function Te(){document.title=`BackToSchool.help — Learn something live`;let{events:e}=await S(`/api/v1/events?limit=60`).catch(()=>({events:[]})),t=e.filter(e=>e.status===`live`||e.status===`starting`),n=e.filter(e=>e.status===`scheduled`||e.status===`draft`),r=e.filter(e=>e.status===`ended`&&e.recordingId);T.innerHTML=`
|
|
32
|
-
<section class="hero">
|
|
33
|
-
<div class="hero-copy">
|
|
34
|
-
<span class="eyebrow">Go back to school whenever you want</span>
|
|
35
|
-
<h1>Learn something<br /><em>live.</em></h1>
|
|
36
|
-
<p>Watch a live lesson, follow a screen share, and ask questions as you learn.</p>
|
|
37
|
-
<div class="hero-actions">
|
|
38
|
-
<button class="button button-primary" type="button" data-event-mode="live"><span class="live-dot"></span><span data-i18n="Go live"> Go live</span></button>
|
|
39
|
-
<button class="button button-secondary" type="button" data-event-mode="scheduled" data-i18n="Schedule live">Schedule live</button>
|
|
40
|
-
</div>
|
|
41
|
-
<p class="hero-note">Watch classes and screen shares. No account required.</p>
|
|
42
|
-
${oe()}
|
|
43
|
-
</div>
|
|
44
|
-
<div class="hero-board" aria-label="What is happening today">
|
|
45
|
-
<span class="tape tape-one" aria-hidden="true"></span>
|
|
46
|
-
<span class="tape tape-two" aria-hidden="true"></span>
|
|
47
|
-
<div class="board-rule"></div>
|
|
48
|
-
<span class="board-label">Today’s lesson</span>
|
|
49
|
-
<strong>${U(t[0]?.title??n[0]?.title??`The best teachers are curious people`)}</strong>
|
|
50
|
-
<p>${t[0]?`Happening right now`:n[0]?q(n[0]):`Host the first live conversation`}</p>
|
|
51
|
-
${t[0]?`<a href="${W(t[0])}" data-link class="board-action"><span data-i18n="Watch now">Watch now </span><span>↗</span></a>`:`<button type="button" data-event-mode="live" class="board-action"><span data-i18n="Start a room">Start a room </span><span>↗</span></button>`}
|
|
52
|
-
<div class="board-doodles" aria-hidden="true"><span>?</span><span>✦</span><span>≈</span></div>
|
|
53
|
-
</div>
|
|
54
|
-
</section>
|
|
55
|
-
|
|
56
|
-
<section class="event-section" id="live">
|
|
57
|
-
<div class="section-heading">
|
|
58
|
-
<div><span class="eyebrow">Walk in anytime</span><h2 data-i18n="Live now">Live now</h2></div>
|
|
59
|
-
<span class="section-count">${t.length} ${t.length===1?`room`:`rooms`}</span>
|
|
60
|
-
</div>
|
|
61
|
-
<div class="event-grid">
|
|
62
|
-
${t.length?t.map(we).join(``):`<div class="empty-card"><span>☕</span><h3>The halls are quiet.</h3><p>Start a live and give people something worth dropping into.</p><button class="text-button" data-event-mode="live" data-i18n="Open a room →">Open a room →</button></div>`}
|
|
63
|
-
</div>
|
|
64
|
-
</section>
|
|
65
|
-
|
|
66
|
-
<section class="event-section event-section-tint" id="upcoming">
|
|
67
|
-
<div class="section-heading">
|
|
68
|
-
<div><span class="eyebrow">Save your seat</span><h2 data-i18n="Coming up">Coming up</h2></div>
|
|
69
|
-
</div>
|
|
70
|
-
<div class="upcoming-list">
|
|
71
|
-
${n.length?n.map(e=>`
|
|
72
|
-
<a class="upcoming-row" href="${W(e)}" data-link>
|
|
73
|
-
<time>${U(K(e.startsAt,{weekday:`short`,month:`short`,day:`numeric`}))}</time>
|
|
74
|
-
<span><strong>${U(e.title)}</strong><small>${U(e.topic||`Live conversation`)}</small></span>
|
|
75
|
-
<span class="row-arrow">→</span>
|
|
76
|
-
</a>`).join(``):`<p class="empty-line">Nothing scheduled yet. Your idea could be next.</p>`}
|
|
77
|
-
</div>
|
|
78
|
-
</section>
|
|
79
|
-
|
|
80
|
-
${r.length?`<section class="event-section"><div class="section-heading"><div><span class="eyebrow" data-i18n="Listen after class">Listen after class</span><h2 data-i18n="Recent replays">Recent replays</h2></div></div><div class="event-grid">${r.map(we).join(``)}</div></section>`:``}
|
|
81
|
-
|
|
82
|
-
<section class="host-callout">
|
|
83
|
-
<span class="eyebrow">Know a thing or two?</span>
|
|
84
|
-
<h2>Someone wants to hear it.</h2>
|
|
85
|
-
<p>You don’t need a studio or a syllabus. Bring an idea and start talking.</p>
|
|
86
|
-
<button class="button button-light" type="button" data-event-mode="scheduled" data-i18n="Plan a conversation">Plan a conversation</button>
|
|
87
|
-
</section>`}function Ee(e){let t=le(e.broadcastUrl);if(t)return`<div class="classroom-video"><iframe src="${U(t.embed)}" title="${U(e.title)} broadcast" allow="autoplay; fullscreen; picture-in-picture; encrypted-media" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe></div>
|
|
88
|
-
<p class="broadcast-caption"><a class="button button-secondary" href="${U(t.join)}" target="_blank" rel="noopener noreferrer">${t.provider===`pairux`?`Join screen share on Pairux`:`Open video in Nixamp`} ↗</a></p>`;let n=G(),r=e.recordingId&&e.status===`ended`?`/api/v1/recordings/${encodeURIComponent(e.recordingId)}`:`/api/channels/${encodeURIComponent(e.roomId)}${n}`,i=e.status===`live`||!!e.recordingId;return`
|
|
89
|
-
<div class="listen-card ${i?``:`waiting`}">
|
|
90
|
-
<div class="sound-orbit" aria-hidden="true"><span></span><span></span><span></span><b>▶</b></div>
|
|
91
|
-
<div>
|
|
92
|
-
<span class="eyebrow">${e.status===`live`?`On air now`:e.recordingId?p(`Replay`):`The room opens soon`}</span>
|
|
93
|
-
<h2>${i?e.status===`live`?`Listen live`:`Listen again`:`We’ll see you here.`}</h2>
|
|
94
|
-
<p id="player-note">${i?`Press play and you’re in. No sign-up, no setup.`:U(q(e))}</p>
|
|
95
|
-
${i?`<button class="button button-primary listen-button" type="button" data-listen><span class="live-dot"></span> ${e.status===`live`?`Listen live`:`Play replay`}</button><audio id="event-audio" preload="none" src="${U(r)}" controls></audio>`:``}
|
|
96
|
-
</div>
|
|
97
|
-
</div>`}function De(e){return e.chatEnabled?`
|
|
98
|
-
<div id="chat-messages" class="chat-messages"><p class="muted">Loading the conversation…</p></div>
|
|
99
|
-
${F?`<form id="chat-form" class="inline-form"><input name="body" maxlength="1000" placeholder="Add to the conversation" data-i18n-placeholder="Add to the conversation" aria-label="Chat message" data-i18n-aria-label="Chat message" required /><button class="button button-small" type="submit" data-i18n="Send">Send</button></form>`:`<button class="text-button" type="button" data-sign-in>Sign in to join the chat →</button>`}`:`<div class="panel-empty">Chat is off for this event.</div>`}function Oe(e,t){switch(e){case`event-header`:return`<div class="event-heading"><span class="status-pill ${t.status===`live`?`status-live`:``}">${U(q(t))}</span>${t.topic?`<span class="topic">${U(t.topic)}</span>`:``}<h1>${U(t.title)}</h1><p>${U(t.description||`A live conversation powered by NixAmp.`)}</p><button class="button button-secondary follow-event" type="button" data-follow-owner="${U(t.ownerId)}" data-following="unknown" data-i18n="Follow host">Follow host</button><p class="form-note" id="follow-note" role="status"></p></div>`;case`player`:return Ee(t);case`stage`:return`<div class="stage-card"><span class="stage-avatar">${U(t.title.slice(0,1).toUpperCase())}</span><div><span class="eyebrow" data-i18n="Host stage">Host stage</span><h2>${U(t.title)}</h2><p id="broadcast-note">${t.status===`live`?`This event is live.`:`Start when you’re ready.`}</p></div></div>`;case`host`:return`<div class="host-line">${t.avatarUrl?`<img class="avatar host-avatar" src="${U(t.avatarUrl)}" alt="" referrerpolicy="no-referrer" />`:`<span class="avatar">${U((t.hostName||t.title).slice(0,1))}</span>`}<div><small data-i18n="Your host">Your host</small><strong>${U(t.hostName||p(`Class host`))}</strong>${t.homepageUrl?`<a href="${U(t.homepageUrl)}" target="_blank" rel="noopener noreferrer">Visit homepage ↗</a>`:``}</div></div>`;case`about`:return`<p class="reading-copy">${U(t.description||`Come listen, learn, and ask a question live.`)}</p>${t.topic?`<span class="topic topic-large">${U(t.topic)}</span>`:``}`;case`join`:return F?`<p class="panel-empty">You’re signed in and ready to participate.</p>`:`<div class="join-line"><div><strong>Want to ask something?</strong><p>Join with your NixAmp account.</p></div><button class="button button-secondary" type="button" data-sign-in data-i18n="Join in">Join in</button></div>`;case`chat`:return De(t);case`questions`:return`<div class="panel-empty">Questions shared in chat can be brought onto the stage.</div>`;case`resources`:return`<div class="panel-empty">The host hasn’t added resources yet.</div>`;case`participants`:return`<div class="metric"><strong id="listener-count">—</strong><span>listening now</span></div>`;case`speakers`:return`<div class="people-row"><span class="avatar">H</span><span><strong data-i18n="Host">Host</strong><small>On stage</small></span></div>`;case`raise-hand`:return t.handRaiseEnabled?`<div class="join-line"><div><strong>Have something to add?</strong><p>Let the host know you’d like to speak.</p></div><button class="button button-secondary" type="button" data-raise-hand data-i18n="Raise hand">Raise hand</button></div>`:null;case`hand-raises`:return`<div id="hand-raises" class="hand-raises"><p class="muted">No hands raised.</p></div>`;case`invite`:return`<form id="invite-form" class="form-stack compact"><label><span data-i18n="Email">Email</span><input name="email" type="email" placeholder="someone@example.com" required /></label><label><span data-i18n="Invite as">Invite as</span><select name="role"><option value="listener" data-i18n="Listener">Listener</option><option value="speaker" data-i18n="Speaker">Speaker</option><option value="moderator" data-i18n="Moderator">Moderator</option></select></label><button class="button button-small" type="submit" data-i18n="Create invite">Create invite</button><p id="invite-note" class="form-note"></p></form>`;case`share`:return`<div class="share-box"><input id="share-url" value="${U(location.href)}" readonly aria-label="Event URL" /><button class="button button-small" type="button" data-copy data-i18n="Copy link">Copy link</button></div>`;case`event-controls`:return`<div class="control-stack">
|
|
100
|
-
<a href="https://pairux.com/dashboard" target="_blank" rel="noopener noreferrer" data-i18n="Screen share with Pairux ↗">Screen share with Pairux ↗</a>
|
|
101
|
-
<a href="https://nixamp.com/#files-panel" target="_blank" rel="noopener noreferrer" data-i18n="Upload & broadcast in Nixamp ↗">Upload & broadcast in Nixamp ↗</a>
|
|
102
|
-
${[`draft`,`scheduled`,`starting`].includes(t.status)?`<button class="button button-primary" type="button" data-start-event data-i18n="Start class">Start class</button>`:``}
|
|
103
|
-
<button class="button button-danger" type="button" data-end-event ${t.status===`live`?``:`hidden`}>${t.recurrence?`End session & schedule next`:p(`End event`)}</button>
|
|
104
|
-
<p id="broadcast-note" class="form-note" role="status">${t.broadcastUrl?`Start the broadcast in Pairux or Nixamp, then start the class here.`:`Add your broadcast link with Edit event.`}</p>
|
|
105
|
-
</div>`;case`schedule`:return`<div class="metric"><strong>${U(K(t.startsAt,{timeZone:t.timezone}))}</strong><span>${U(t.timezone)}${t.recurrence?` · Repeats ${t.recurrence}`:``}</span></div>`;case`recording`:return`<div class="control-line"><span>${t.recordingEnabled?`Recording requested`:`Recording is off`}</span><span class="status-dot ${t.recordingEnabled?`on`:``}"></span></div>`;default:return null}}async function ke(e){let t=await S(`/api/v1/events/${encodeURIComponent(e)}${G()}`);V?.(),V=null,H=t;let n=t.event;document.title=`${n.title} — BackToSchool.help`,document.querySelector(`meta[name="description"]`)?.setAttribute(`content`,n.description||`Listen to ${n.title} live on BackToSchool.help.`),document.querySelector(`meta[property="og:title"]`)?.setAttribute(`content`,n.title),document.querySelector(`meta[property="og:description"]`)?.setAttribute(`content`,n.description||p(`Learn something live.`));let r=(e,t)=>`<section class="event-panel panel-${e}"><h2 class="panel-title">${t}</h2>${Oe(e,n)??``}</section>`;T.innerHTML=`
|
|
106
|
-
<div class="event-shell">
|
|
107
|
-
<div class="event-toolbar"><a class="back-link" href="/" data-link>← Explore more lives</a>${F?.id===n.ownerId?`<button class="button button-secondary" type="button" data-edit-event data-i18n="Edit event">Edit event</button>`:``}</div>
|
|
108
|
-
<div class="class-update" hidden><p id="event-update" role="status" class="form-note"></p><button class="text-button" data-refresh-event>Refresh class details</button><button class="text-button" data-dismiss-update>Dismiss</button></div>
|
|
109
|
-
<div class="event-layout">
|
|
110
|
-
<div class="region region-primary">${r(`event-header`,`Live classroom`)}${r(`player`,`Watch class`)}${r(`chat`,`Class chat`)}</div>
|
|
111
|
-
<aside class="region region-secondary">${r(`host`,`Meet your host`)}${r(`schedule`,p(`Schedule`))}${F?.id===n.ownerId?r(`event-controls`,`Host controls`):r(`join`,`Join the class`)}${F?.id===n.ownerId&&n.visibility===`private`?`<details class="event-panel"><summary>Invite students</summary>${Oe(`invite`,n)}</details>`:``}${r(`share`,`Share class`)}${F?.id===n.ownerId&&n.handRaiseEnabled?r(`hand-raises`,`Raised hands`):n.handRaiseEnabled?r(`raise-hand`,`Ask a question`):``}</aside>
|
|
112
|
-
</div>
|
|
113
|
-
</div>`,Ae(n)}function Ae(e){document.querySelector(`[data-listen]`)?.addEventListener(`click`,async e=>{let t=e.currentTarget,n=document.querySelector(`#event-audio`);if(n){t.disabled=!0,g(t,()=>p(`Connecting…`));try{await n.play(),t.textContent=`You’re listening`,document.querySelector(`#player-note`).textContent=`Live audio from this NixAmp room.`}catch{t.disabled=!1,t.textContent=`Try listening again`,document.querySelector(`#player-note`).textContent=`The host may still be getting ready. Try again in a moment.`}}});let t=document.querySelector(`#chat-form`);t?.addEventListener(`submit`,n=>{n.preventDefault();let r=t.elements.namedItem(`body`),i=r.value.trim();i&&(r.value=``,C(`/api/v1/events/${encodeURIComponent(e.id)}/chat`,{body:i}).then(()=>je(e)).catch(e=>{r.placeholder=e instanceof Error?e.message:`Could not send`}))});let n=document.querySelector(`#invite-form`);n?.addEventListener(`submit`,t=>{t.preventDefault();let r=new FormData(n),i=document.querySelector(`#invite-note`);i.textContent=`Creating invite…`,S(`/api/v1/events/${encodeURIComponent(e.id)}/invitations`,{method:`POST`,body:JSON.stringify({email:r.get(`email`),role:r.get(`role`)})}).then(async({inviteUrl:e,sent:t})=>{await navigator.clipboard?.writeText(e).catch(()=>void 0),i.textContent=t?`Invite sent. The link is copied too.`:`Invite link copied: ${e}`,n.reset()}).catch(e=>{i.textContent=e instanceof Error?e.message:`Could not invite`})}),document.querySelector(`[data-raise-hand]`)?.addEventListener(`click`,t=>{let n=t.currentTarget;n.disabled=!0,C(`/api/v1/events/${encodeURIComponent(e.id)}/hand-raises`,{}).then(()=>{g(n,()=>p(`Hand raised ✓`))}).catch(e=>{n.disabled=!1,n.textContent=e instanceof x&&e.status===401?`Sign in to raise hand`:`Try again`})}),document.querySelector(`[data-edit-event]`)?.addEventListener(`click`,()=>Z(`scheduled`,H.event));let r=document.querySelector(`[data-follow-owner]`);if(r){let e=r.dataset.followOwner??``;S(`/api/v1/follows/${encodeURIComponent(e)}`).then(({following:e})=>{r.dataset.following=e?`yes`:`no`,g(r,()=>p(e?`Following`:`Follow host`))}).catch(()=>void 0),r.addEventListener(`click`,()=>{if(!F){Y(()=>void $());return}let t=r.dataset.following===`yes`;r.disabled=!0,S(`/api/v1/follows/${encodeURIComponent(e)}`,{method:t?`DELETE`:`PUT`,body:t?void 0:`{}`}).then(({following:e})=>{r.dataset.following=e?`yes`:`no`,g(r,()=>p(e?`Following`:`Follow host`));let t=document.querySelector(`#follow-note`);t&&g(t,()=>p(e?`You’ll get email and web notifications for this host.`:`Notifications turned off for this host.`)),e&&ve()}).catch(e=>{let t=document.querySelector(`#follow-note`);t&&(t.textContent=e instanceof Error?e.message:`Could not update notifications.`)}).finally(()=>{r.disabled=!1})})}document.querySelector(`[data-start-event]`)?.addEventListener(`click`,()=>void Pe()),document.querySelector(`[data-dismiss-update]`)?.addEventListener(`click`,()=>document.querySelector(`.class-update`).hidden=!0),document.querySelector(`[data-refresh-event]`)?.addEventListener(`click`,()=>Q(W(e)+G())),document.querySelector(`[data-end-event]`)?.addEventListener(`click`,()=>void Fe()),document.querySelector(`[data-copy]`)?.addEventListener(`click`,async e=>{await navigator.clipboard.writeText(location.href),g(e.currentTarget,()=>p(`Copied ✓`))});let i=0,a=0;e.chatEnabled&&(je(e),i=window.setInterval(()=>void je(e),4e3),a=xe(`event.moderate`)?window.setInterval(()=>void Me(e),3e3):0,Me(e));let o=e.version,s=window.setInterval(()=>void S(`/api/v1/events/${encodeURIComponent(e.id)}${G()}`).then(e=>{if(e.event.version===H?.event.version||e.event.version===o)return;o=e.event.version;let t=document.querySelector(`.event-heading .status-pill`),n=q(e.event);t&&t.textContent!==n&&(t.textContent=n,t.classList.toggle(`status-live`,e.event.status===`live`)),be(`The host updated this class. Refresh the details when you’re ready.`)}).catch(()=>void 0),5e3);V=()=>{clearInterval(i),clearInterval(a),clearInterval(s)},Ne(e)}async function je(e){let t=document.querySelector(`#chat-messages`);if(t)try{let{messages:n}=await S(`/api/v1/events/${encodeURIComponent(e.id)}/chat${G()}`);ye(t,n.length?n.map(e=>`<div class="chat-message"><span class="avatar avatar-small">${U(e.authorName.slice(0,1).toUpperCase())}</span><p><strong>${U(e.authorName)}</strong><span>${U(e.body)}</span></p></div>`).join(``):`<p class="muted">No messages yet. Say hello when you’re ready.</p>`)}catch{t.innerHTML=`<p class="muted">Chat is taking a break. You can still watch the class.</p>`}}async function Me(e){let t=document.querySelector(`#hand-raises`);if(t&&xe(`event.moderate`))try{let{handRaises:n}=await S(`/api/v1/events/${encodeURIComponent(e.id)}/hand-raises`);if(t.contains(document.activeElement))return;ye(t,n.length?n.map(e=>`<div class="raise-row"><span><strong>${U(e.displayName)}</strong><small>${U(e.state)}</small></span><div><button class="text-button" data-hand="${U(e.accountId)}" data-state="invited"><span data-i18n="Invite">Invite</span></button><button class="text-button" data-hand="${U(e.accountId)}" data-state="dismissed">Dismiss</button></div></div>`).join(``):`<p class="muted">No hands raised.</p>`)}catch{t.contains(document.activeElement)||(t.innerHTML=`<p class="muted">Could not refresh hand raises.</p>`)}}async function Ne(e){let t=document.querySelector(`#listener-count`);if(t)try{let{channels:n}=await S(`/api/channels`);t.textContent=String(n.find(t=>t.id===e.roomId)?.listeners??0)}catch{t.textContent=`0`}}async function Pe(){if(!H)return;let e=document.querySelector(`#broadcast-note`),t=document.querySelector(`[data-start-event]`);if(!H.event.broadcastUrl){e&&(e.textContent=`Add a Pairux or Nixamp broadcast link with Edit event first.`);return}if(t?.getAttribute(`aria-disabled`)!==`true`){t?.setAttribute(`aria-disabled`,`true`);try{H=await S(`/api/v1/events/${encodeURIComponent(H.event.id)}/start`,{method:`POST`,body:JSON.stringify({version:H.event.version})}),t&&(t.textContent=`Class is live`),document.querySelector(`[data-end-event]`)?.removeAttribute(`hidden`);let n=document.querySelector(`.event-heading .status-pill`);n&&(g(n,()=>p(`Live now`)),n.classList.add(`status-live`)),e&&(e.textContent=`Your class is live. Viewers can join using this page.`)}catch(n){t?.removeAttribute(`aria-disabled`),e&&(e.textContent=n instanceof Error?n.message:`Could not start the class.`)}}}async function Fe(){let e=document.querySelector(`[data-end-event]`);if(!H||e?.getAttribute(`aria-disabled`)===`true`)return;e?.setAttribute(`aria-disabled`,`true`);let t=H.event;try{let e=await S(`/api/v1/events/${encodeURIComponent(t.id)}/end`,{method:`POST`,body:JSON.stringify({version:t.version})});H=e;let n=document.querySelector(`.event-heading .status-pill`);n&&(n.textContent=q(e.event),n.classList.remove(`status-live`)),await fetch(`/api/channels/${encodeURIComponent(t.roomId)}`,{method:`DELETE`,credentials:`same-origin`});let r=document.querySelector(`#broadcast-note`);r&&(r.textContent=e.event.recurrence?`Session ended. Next class: ${K(e.event.startsAt)}. End the broadcast in Pairux or Nixamp too.`:`Event ended. End the broadcast in Pairux or Nixamp too.`);let i=document.querySelector(`[data-end-event]`);i&&(g(i,()=>p(`Session ended`)),i.setAttribute(`aria-disabled`,`true`)),be(`This session has ended. Refresh to see the latest schedule.`)}catch(t){e?.removeAttribute(`aria-disabled`);let n=document.querySelector(`#broadcast-note`);n&&(n.textContent=t instanceof Error?t.message:`Could not end the event.`)}}async function $(){V?.(),V=null,H=null;let e=/^\/live\/([^/]+)\/?$/.exec(location.pathname);try{e?await ke(decodeURIComponent(e[1])):await Te()}catch(e){T.innerHTML=`<section class="error-page"><span class="eyebrow">Class dismissed?</span><h1>${U(e instanceof x&&e.status===404?`That live event isn’t available.`:`We couldn’t open this page.`)}</h1><p>${U(e instanceof Error?e.message:`Try again in a moment.`)}</p><a href="/" data-link class="button button-primary">Back to live events</a></section>`}}E.addEventListener(`click`,()=>{if(!F){Y();return}confirm(`Signed in as ${F.email}. Sign out?`)&&S(`/api/v1/auth/logout`,{method:`POST`}).finally(()=>{F=null,J(),$()})}),fe.addEventListener(`click`,()=>{I=!I,k.textContent=``,Ce()}),O.addEventListener(`submit`,e=>{e.preventDefault();let t=new FormData(O),n=O.querySelector(`button[type="submit"]`);n.disabled=!0,k.textContent=``,S(`/api/v1/auth/${I?`signup`:`login`}`,{method:`POST`,body:JSON.stringify({email:t.get(`email`),password:t.get(`password`)})}).then(e=>{F=e.account,J(),O.reset(),D.close();let t=B;B=null,t?t():$()}).catch(e=>{k.textContent=e instanceof Error?e.message:`That did not work.`}).finally(()=>{n.disabled=!1})}),j.querySelector(`[name="recurrence"]`)?.addEventListener(`change`,()=>{j.elements.namedItem(`recurrence`).value!==`none`&&(L=!0,P.hidden=!1,j.elements.namedItem(`startsAt`).required=!0)}),j.addEventListener(`submit`,e=>{if(e.preventDefault(),z)return;let t=new FormData(j),n=R,r=String(t.get(`startsAt`)??``),i=!n?.startsAt||r!==X(n.startsAt),a=String(t.get(`recurrence`));if(a!==`none`&&!r&&!L){L=!0,P.hidden=!1,j.elements.namedItem(`startsAt`).required=!0,N.textContent=`Choose the first class date and time for this recurring schedule.`;return}z=!0,M.setAttribute(`aria-disabled`,`true`),j.setAttribute(`aria-busy`,`true`),N.textContent=``;let o={title:t.get(`title`),description:t.get(`description`),topic:t.get(`topic`),visibility:t.get(`visibility`),broadcastUrl:t.get(`broadcastUrl`),hostName:t.get(`hostName`),homepageUrl:t.get(`homepageUrl`),avatarUrl:t.get(`avatarUrl`),recurrence:a,chatEnabled:t.get(`chatEnabled`)===`on`,handRaiseEnabled:t.get(`handRaiseEnabled`)===`on`,...n?{version:n.version}:{kind:`class`},...L?{startsAt:r?i?new Date(r).toISOString():n.startsAt:null,timezone:i?Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`:n.timezone,expectedDurationMinutes:Number(t.get(`expectedDurationMinutes`))}:{}};S(n?`/api/v1/events/${encodeURIComponent(n.id)}`:`/api/v1/events`,{method:n?`PATCH`:`POST`,body:JSON.stringify(o)}).then(async e=>{n?(await ke(e.event.slug),A.close(),document.querySelector(`[data-edit-event]`)?.focus({preventScroll:!0})):(A.close(),Q(W(e.event))),j.reset(),R=null}).catch(e=>{N.textContent=e instanceof Error?e.message:`Could not save the event.`}).finally(()=>{z=!1,M.removeAttribute(`aria-disabled`),j.removeAttribute(`aria-busy`)})}),document.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`a[data-link]`);if(n&&n.origin===location.origin){e.preventDefault(),Q(`${n.pathname}${n.search}`);return}let r=t.closest(`[data-event-mode]`)?.dataset.eventMode;(r===`live`||r===`scheduled`)&&Z(r),t.closest(`[data-sign-in]`)&&Y(()=>void $());let i=t.closest(`[data-close]`);i&&i.closest(`dialog`)?.close();let a=t.closest(`[data-hand]`);a&&H&&(a.disabled=!0,C(`/api/v1/events/${encodeURIComponent(H.event.id)}/hand-raises/${encodeURIComponent(a.dataset.hand??``)}`,{state:a.dataset.state},`PATCH`).then(()=>Me(H.event)).finally(()=>{a.disabled=!1}))}),window.addEventListener(`popstate`,()=>void $()),Se().then(()=>$());export{e as t};
|