HashNavigation 改名 Navigation(src/lib/navigation.js),接口不变,内部改用真实路径: parseUrlHash/composeUrlHash 改名 parseUrl/composeUrl;navigateTo/navigateReplace 改调 pushState/replaceState 后手动派发 popstate(pushState/replaceState 不会像赋值 location.hash 那样自动触发事件,这里复用 navigateReplace 早就在用的同一个手动 dispatch 手法);goBack() 不用改,history.back() 本来就是真实浏览器历史机制。新增 Navigation.currentUrl() 替代调用方 原本直接读的 window.location.hash(这个类从来没包装过这个读取)。 一处需要专门处理的边界情况:当 path[0] 是空字符串("不选中侧栏视图、只开一个会话"这个仓库里 的合法状态)时,拼出的真实路径开头会变成双斜杠,被浏览器当协议相对地址解析、试图跳到一个叫 会话id的host,pushState 直接抛 SecurityError。composeUrl/parseUrl 内部用占位 token "_" 处理 这种情况,对外的调用方(19个文件)完全无感。 tinode-web.jsx 的 handleHashRoute 改名 handleRouteChange,监听从 hashchange 换成 popstate; service-worker.js 的推送通知点击跳转手动改写成同样的路径格式(这个文件在打包之外单独执行, 没法 import Navigation)。index.html/index-dev.html 加了 <base href="/">——所有静态资源引用 都是相对路径,hash 路由下页面路径永远是 /,换真实路径后深层地址刷新会按当前目录解析出错误 资源地址导致白屏,这一行是标准修法。nginx.conf 的 try_files 兜底规则本来就适用两种路由,只 更新了注释。 实机验证:地址栏不再有 #;点击会话/设置等各类视图正常跳转;浏览器前进后退和应用内"返回" 按钮都正常;收藏页内部的类型 tab 切换(navigateReplace)确认不产生新的历史记录;在会话页/ 个人中心页刷新、直接用完整深层路径打开新标签页都能正确恢复到位,资源正常加载不白屏。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2 lines
9.9 KiB
JavaScript
2 lines
9.9 KiB
JavaScript
"use strict";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[331],{6331:function(e,s,i){i.r(s);var t=i(1594),n=i.n(t),a=i(8181),o=i(3207),l=i(6948),d=i(9022),r=i(4848);const c=(0,a.defineMessages)({delete_account:{id:"delete_account",defaultMessage:"Delete account",description:"Title for delete account warning"},delete_account_warning:{id:"delete_account_warning",defaultMessage:"Are you sure you want to delete your account? It cannot be undone.",description:"Warning message when deleting an account"}});class h extends n().Component{constructor(e){super(e);const s=this.props.tinode.getMeTopic();let i=0;s.contacts(e=>{e.acs&&!e.acs.isJoiner()&&i++});const t=s.getDefaultAccess();this.state={auth:t?t.auth:null,anon:t?t.anon:null,showPermissionEditorFor:void 0,blockedCount:i},this.handlePasswordUpdate=this.handlePasswordUpdate.bind(this),this.handleLaunchPermissionsEditor=this.handleLaunchPermissionsEditor.bind(this),this.handleHidePermissionsEditor=this.handleHidePermissionsEditor.bind(this),this.handlePermissionsChanged=this.handlePermissionsChanged.bind(this),this.handleDeleteAccount=this.handleDeleteAccount.bind(this),this.handleLogoutRequest=this.handleLogoutRequest.bind(this),this.handleCheckboxClick=this.handleCheckboxClick.bind(this)}handlePasswordUpdate(e){this.setState({password:e}),this.props.onUpdatePassword(e)}handleLaunchPermissionsEditor(e){this.setState({showPermissionEditorFor:e,editedPermissions:this.state[e]})}handleHidePermissionsEditor(){this.setState({showPermissionEditorFor:void 0})}handlePermissionsChanged(e){let s={};s[this.state.showPermissionEditorFor]=e,this.props.onUpdateAccountDesc("me",void 0,void 0,s);let i={showPermissionEditorFor:void 0};i[this.state.showPermissionEditorFor]=e,this.setState(i)}handleCheckboxClick(e,s){this.props.onToggleIncognitoMode(s)}handleDeleteAccount(e){e.preventDefault();const{formatMessage:s}=this.props.intl;this.props.onShowAlert(s(c.delete_account),s(c.delete_account_warning),e=>this.props.onDeleteAccount(),null,!0,null)}handleLogoutRequest(e){e.preventDefault(),this.props.onShowAlert("退出登录","确定要退出当前登录吗?",e=>this.props.onLogout(),null,!0,null)}render(){return(0,r.jsx)(r.Fragment,{children:this.state.showPermissionEditorFor?(0,r.jsx)(d.A,{mode:this.state.editedPermissions,skip:"O",onSubmit:this.handlePermissionsChanged,onCancel:this.handleHidePermissionsEditor}):(0,r.jsxs)("div",{className:"scrollable-panel",children:[(0,r.jsxs)("div",{className:"panel-form-column",children:[(0,r.jsx)("label",{className:"small",children:(0,r.jsx)(a.FormattedMessage,{id:"label_password",defaultMessage:"Password",description:"Label for password editing"})}),(0,r.jsx)("div",{children:(0,r.jsx)(a.FormattedMessage,{id:"password_unchanged_prompt",defaultMessage:"Unchanged",description:"Message in editor while password is unchanged",children:e=>(0,r.jsx)(l.A,{placeholder:e,type:"password",onFinished:this.handlePasswordUpdate})})})]}),(0,r.jsx)("div",{className:"hr"}),(0,r.jsxs)("div",{className:"panel-form-row",children:[(0,r.jsx)("label",{htmlFor:"incognito-mode",children:(0,r.jsx)(a.FormattedMessage,{id:"label_incognito_mode",defaultMessage:"Incognito mode:",description:"Label for incognito mode toggle"})}),(0,r.jsx)(o.A,{name:"incognito",id:"incognito-mode",checked:this.props.incognitoMode,onChange:this.handleCheckboxClick})]}),(0,r.jsx)("div",{className:"panel-form-row",children:(0,r.jsx)("span",{className:"small gray",children:(0,r.jsx)(a.FormattedMessage,{id:"incognito_mode_description",defaultMessage:"Hide your online status and typing indicators.",description:"Description for incognito mode toggle"})})}),(0,r.jsx)("div",{className:"hr"}),(0,r.jsxs)("div",{className:"panel-form-column security-product-links",children:[(0,r.jsxs)("button",{type:"button",className:"flat-button",onClick:()=>this.props.onNavigate("realname"),children:[(0,r.jsx)("i",{className:"material-icons",children:"verified_user"}),(0,r.jsx)("span",{children:"实名认证"}),(0,r.jsx)("i",{className:"material-icons trailing",children:"chevron_right"})]}),(0,r.jsxs)("button",{type:"button",className:"flat-button",onClick:()=>this.props.onNavigate("identity-check"),children:[(0,r.jsx)("i",{className:"material-icons",children:"phonelink_lock"}),(0,r.jsx)("span",{children:"身份验证"}),(0,r.jsx)("i",{className:"material-icons trailing",children:"chevron_right"})]}),(0,r.jsxs)("button",{type:"button",className:"flat-button",onClick:()=>this.props.onNavigate("independent-password"),children:[(0,r.jsx)("i",{className:"material-icons",children:"password"}),(0,r.jsx)("span",{children:"设置独立密码"}),(0,r.jsx)("i",{className:"material-icons trailing",children:"chevron_right"})]})]}),(0,r.jsx)("div",{className:"hr"}),(0,r.jsxs)("div",{className:"panel-form-column",children:[(0,r.jsxs)("a",{href:"#",className:"danger flat-button",onClick:this.handleLogoutRequest,children:[(0,r.jsx)("i",{className:"material-icons",children:"exit_to_app"})," ",(0,r.jsx)(a.FormattedMessage,{id:"button_logout",defaultMessage:"Logout",description:"Button [Logout]"})]}),(0,r.jsxs)("a",{href:"#",className:"danger flat-button",onClick:e=>{this.handleDeleteAccount(e)},children:[(0,r.jsx)("i",{className:"material-icons",children:"delete"})," ",(0,r.jsx)(a.FormattedMessage,{id:"button_delete_account",defaultMessage:"Delete account",description:"Button [Delete account]"})]})]}),(0,r.jsx)("div",{className:"hr"}),(0,r.jsxs)("div",{className:"panel-form-column",children:[(0,r.jsx)("div",{children:(0,r.jsx)("label",{className:"small",children:(0,r.jsx)(a.FormattedMessage,{id:"label_default_access_mode",defaultMessage:"Default access mode:",description:"Label for default access mode"})})}),(0,r.jsxs)("div",{className:"quoted",children:[(0,r.jsxs)("div",{children:["Auth: ",(0,r.jsx)("tt",{className:"clickable",onClick:this.handleLaunchPermissionsEditor.bind(this,"auth"),children:this.state.auth})]}),(0,r.jsxs)("div",{children:["Anon: ",(0,r.jsx)("tt",{className:"clickable",onClick:this.handleLaunchPermissionsEditor.bind(this,"anon"),children:this.state.anon})]})]})]}),this.state.blockedCount>0?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("div",{className:"hr"}),(0,r.jsxs)("div",{className:"panel-form-row",children:[(0,r.jsx)("i",{className:"material-icons",children:"block"})," ",(0,r.jsx)("a",{href:"#",className:"gray",onClick:e=>{e.preventDefault(),this.props.onShowBlocked()},children:(0,r.jsx)(a.FormattedMessage,{id:"blocked_contacts_link",defaultMessage:"Blocked contacts ({count})",values:{count:this.state.blockedCount},description:"Blocked contacts link"})})]})]}):null]})})}}s.default=(0,a.injectIntl)(h)},9022:function(e,s,i){var t=i(1594),n=i.n(t),a=i(8181),o=i(3207),l=i(1974),d=i(7981),r=i(4848);const c=(0,a.defineMessages)({joiner:{id:"permission_join",defaultMessage:"Join ({val})",description:"Name of J permission"},reader:{id:"permission_read",defaultMessage:"Read ({val})",description:"Name of R permission"},writer:{id:"permission_write",defaultMessage:"Write ({val})",description:"Name of W permission"},preser:{id:"permission_pres",defaultMessage:"Get notified ({val})",description:"Name of P permission"},approver:{id:"permission_admin",defaultMessage:"Approve ({val})",description:"Name of A permission"},sharer:{id:"permission_share",defaultMessage:"Share ({val})",description:"Name of S permission"},deleter:{id:"permission_delete",defaultMessage:"Delete ({val})",description:"Name of D permission"},owner:{id:"permission_owner",defaultMessage:"Owner ({val})",description:"Name of O permission"}});class h extends n().Component{constructor(e){super(e),this.state={mode:(e.mode||"").replace("N","")},this.handleChange=this.handleChange.bind(this),this.handleSubmit=this.handleSubmit.bind(this),this.handleCancel=this.handleCancel.bind(this)}handleChange(e){let s=this.state.mode;-1==s.indexOf(e)?s+=e:s=s.replace(e,""),this.setState({mode:s})}handleSubmit(){const e=(this.state.mode||"N").split("").sort().join("");e!==(this.props.mode||"N").split("").sort().join("")?this.props.onSubmit(e):this.props.onCancel()}handleCancel(){this.props.onCancel()}render(){const{formatMessage:e}=this.props.intl,s={J:e(c.joiner,{val:"J"}),R:e(c.reader,{val:"R"}),W:e(c.writer,{val:"W"}),P:e(c.preser,{val:"P"}),A:e(c.approver,{val:"A"}),S:e(c.sharer,{val:"S"}),D:e(c.deleter,{val:"D"}),O:e(c.owner,{val:"O"})};let i=this.props.skip||"",t=this.state.mode,n=(this.props.compare||"").replace("N",""),h=[];for(let e=0;e<8;e++){let a="JRWPASDO".charAt(e);i.indexOf(a)>=0&&t.indexOf(a)<0||h.push((0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:s[a]}),(0,r.jsx)("td",{className:"checkbox",children:i.indexOf(a)<0?(0,r.jsx)(o.A,{name:a,checked:t.indexOf(a)>=0,onChange:this.handleChange}):(0,r.jsx)(o.A,{name:a,checked:t.indexOf(a)>=0})}),this.props.compare?(0,r.jsx)("td",{className:"checkbox",children:(0,r.jsx)(o.A,{name:a,checked:n.indexOf(a)>=0})}):null]},a))}return(0,r.jsxs)("div",{className:"panel-form-column",children:[this.props.userTitle?(0,r.jsx)("ul",{className:"contact-box small",children:(0,r.jsx)(l.A,{tinode:this.props.tinode,item:this.props.item,title:this.props.userTitle,small:!0,avatar:(0,d.to)(this.props.userAvatar?this.props.userAvatar:null)})}):null,(0,r.jsx)("label",{className:"small",children:(0,r.jsx)(a.FormattedMessage,{id:"title_permissions",defaultMessage:"Permissions",description:"Section title"})}),(0,r.jsxs)("table",{className:"permission-editor",children:[this.props.compare?(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("th",{}),(0,r.jsx)("th",{children:this.props.modeTitle}),(0,r.jsx)("th",{children:this.props.compareTitle})]})}):null,(0,r.jsx)("tbody",{children:h})]}),(0,r.jsx)("br",{}),(0,r.jsxs)("div",{className:"dialog-buttons",children:[(0,r.jsx)("button",{className:"outline",onClick:this.handleCancel,children:(0,r.jsx)(a.FormattedMessage,{id:"button_cancel",defaultMessage:"Cancel",description:"Button [Cancel]"})}),(0,r.jsx)("button",{className:"primary",onClick:this.handleSubmit,children:(0,r.jsx)(a.FormattedMessage,{id:"button_ok",defaultMessage:"OK",description:"Button [OK]"})})]})]})}}s.A=(0,a.injectIntl)(h)}}]);
|
||
//# sourceMappingURL=331.prod.js.map
|