const string SELF_USER_STATE_LOGIN = "SELF_USER_STATE_LOGIN"; const string SELF_USER_STATE_GUEST = "SELF_USER_STATE_GUEST"; const string SELF_USER_STATE_NONE = "SELF_USER_STATE_NONE"; component ProfileMenuModel { ProfileMenuViewModel m_ViewModel; string m_VketUserCode; string m_GuestUserCode; string m_Name; string m_Introduction; string m_CircleIconURL; string m_NamePlateIconURL; bool m_IsFirstUpdate; bool m_IsUpdateVCCData; bool m_CheckState; bool m_UpdatedIcon; string m_CurrentSelfUserState; string m_PrevSelfUserState; public ProfileMenuModel() { m_ViewModel = system.Layer_GetComponentByName("config_profile"); m_IsFirstUpdate = true; m_IsUpdateVCCData = false; m_CheckState = false; m_UpdatedIcon = false; m_CurrentSelfUserState = SELF_USER_STATE_NONE; m_PrevSelfUserState = SELF_USER_STATE_NONE; } public void OnNetPosConnected() { // ネットワーク層が古い情報を保持している可能性があるので座標チャンネル接続完了後に再更新する bool Islogin = m_CurrentSelfUserState == SELF_USER_STATE_LOGIN; m_ViewModel.UpdateViewDataByProfile(m_Name, m_Introduction, m_CircleIconURL, m_VketUserCode, ((Islogin) ? "login" : "guest")); } public string GetNamePlateIconURL() { return m_NamePlateIconURL; } public void InitProfile() { // Profile APIの初期化 m_IsUpdateVCCData = true; heliport.v3.api.auths.isLoggedIn(_CheckFirstLoginStateCallback); heliport.v3.api.apiNotification.watchSystem(); } void _CheckFirstLoginStateCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; bool loginValid = result.data.GetBool(); if(loginValid) { m_CurrentSelfUserState = SELF_USER_STATE_LOGIN; m_PrevSelfUserState = SELF_USER_STATE_LOGIN; } else { m_CurrentSelfUserState = SELF_USER_STATE_GUEST; m_PrevSelfUserState = SELF_USER_STATE_GUEST; } _StartFetchProfile(loginValid); } public void FetchProfile(bool IsUpdateVCCData, bool CheckState) { m_IsUpdateVCCData = IsUpdateVCCData; m_CheckState = CheckState; heliport.v3.api.auths.isLoggedIn(_LoggedInCallback); } void _LoggedInCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; bool loginValid = result.data.GetBool(); _StartFetchProfile(loginValid); } void _StartFetchProfile(bool loginValid) { // ログインステータスをチェック if(!loginValid) { // いくつかのプロフィール変更ボタンを非アクティブ状態にする hsCanvasResetToggleDefault("Toggle_MyPage_Is_LoginedIn"); // ログインステータスを更新 m_PrevSelfUserState = m_CurrentSelfUserState; m_CurrentSelfUserState = SELF_USER_STATE_GUEST; } else { // プロフィール変更ボタンを全てアクティブ状態にする hsCanvasResetToggleDefault("Toggle_MyPage_Is_LoginedIn"); hsCanvasToggleChange("Toggle_MyPage_Is_LoginedIn"); // ログインステータスを更新 m_PrevSelfUserState = m_CurrentSelfUserState; m_CurrentSelfUserState = SELF_USER_STATE_LOGIN; } // ログインステータスが変わっているのでユーザー情報を初期化する if(m_CurrentSelfUserState != m_PrevSelfUserState) { // ここの実装もapi.channelSessionApi.refreshChannelSessionに置き換えられそうだが、リリースが近いのでいったんそのままにしておく // initChannelSessionはChS-API内部のユーザー情報を書き換えるために呼んでいるが、Profileクラスで好き勝手に呼ばれると // ChS-APIに入室できなくなってしまうのでVCCクラスに『いったん退出 → initChannelSession → 再入室』の処理を行うようにリクエストを投げている // refreshChannelSessionでこの問題が起こらなくなるとすると置き換えが可能ということに(時間がある時に詳しくチェックする) m_ViewModel.RequestInitSession(); } else // 通常通りProfileを取得する { if(!loginValid) // ゲストユーザー { if(m_GuestUserCode.IsEmpty()) { // GuestUserCodeがないのでChS-APIから取得する // ChS-APIが初期化されていないのであればこの関数は呼べない heliport.v3.api.channelSessionApi.fetchMyProfile(_fetchGuestUserCodeCallback); } else { // ゲストプロフィールを取得 heliport.v3.api.profiles.fetchMyGuestProfile(_fetchMyGuestProfileCallback, m_GuestUserCode); } } else // ログインユーザー { // プロフィールを取得 heliport.v3.api.profiles.fetchMyProfile(_fetchMyProfileCallback); } } } public void ResponseInitSession() { if(m_CurrentSelfUserState == SELF_USER_STATE_GUEST) { _initGuestUserCallback(); } else if(m_CurrentSelfUserState == SELF_USER_STATE_LOGIN) { _InitLoginUserCallback(); } } void _InitLoginUserCallback() { // プロフィールを取得 heliport.v3.api.profiles.fetchMyProfile(_fetchMyProfileCallback); } void _initGuestUserCallback() { // ChS-APIからGuestUserCodeを取得する // ChS-APIが初期化されていないのであればこの関数は呼べない heliport.v3.api.channelSessionApi.fetchMyProfile(_fetchGuestUserCodeCallback); } void _fetchGuestUserCodeCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; JsVal user = result.data.GetProperty("user"); if(user === null) return; string user_code = user.GetProperty("uid").GetStr(); string user_type = user.GetProperty("user_type").GetStr(); // ゲストプロフィールを取得 if(!user_code.IsEmpty() && user_type == "guest") { m_GuestUserCode = user_code; heliport.v3.api.profiles.fetchMyGuestProfile(_fetchMyGuestProfileCallback, m_GuestUserCode); } } void _fetchMyProfileCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; JsVal profile = result.data.GetProperty("profile"); if(profile === null) return; _AnalyseProfileJSON(profile, true); } void _fetchMyGuestProfileCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; _AnalyseProfileJSON(result.data, false); } void _AnalyseProfileJSON(JsVal profile, bool Islogin) { string vket_id; if(profile.GetProperty("vket_id") !== null) vket_id = profile.GetProperty("vket_id").GetStr(); string uuid; if(profile.GetProperty("uuid") !== null) uuid = profile.GetProperty("uuid").GetStr(); string name = profile.GetProperty("name").GetStr(); string introduction = profile.GetProperty("introduction").GetStr(); string url; // ネームプレート横に表示用 string circle_url; // Circle Icon URLの取得はログインユーザーのみ // ゲストユーザーの場合、まずアイコンアップロードは許されておらず、丸型アイコンが生成されることはないため if(m_CurrentSelfUserState == SELF_USER_STATE_LOGIN) { JsVal icon = profile.GetProperty("icon"); if(icon !== null) { JsVal circle = icon.GetProperty("circle"); if(circle !== null) { circle_url = circle.GetProperty("url").GetStr(); } url = icon.GetProperty("url").GetStr(); } } if(!vket_id.IsEmpty()) { m_VketUserCode = vket_id; } else { m_VketUserCode = uuid; } // Profile APIから名前を取得する m_Name = name; m_Introduction = introduction; m_CircleIconURL = circle_url; m_NamePlateIconURL = url; // 座標チャンネルのCustomState上のUserType(VketID)を更新する // 座標チャンネルが変わっても自動的に引き継がれる値 hsNetSetCustomState("UserCode", m_VketUserCode); hsNetSetCustomState("UserType", ((Islogin)? "login" : "guest")); SetUserProfileState(Islogin); // VCCのデータを更新するか if(m_IsUpdateVCCData) { if(m_CheckState) { // ログインステータスが変わっている時のみデータを更新する(何回も更新してるとスマホが重くなりそうなため) if(m_CurrentSelfUserState != m_PrevSelfUserState) { m_ViewModel.UpdateSelfUserData(m_Name, m_Introduction, m_CircleIconURL, m_VketUserCode, ((Islogin)? "login" : "guest")); } } else { m_ViewModel.UpdateSelfUserData(m_Name, m_Introduction, m_CircleIconURL, m_VketUserCode, ((Islogin)? "login" : "guest")); } } // ChS-APIのアイコン変更関数を呼んで、アイコンデータを即時反映させる if(m_UpdatedIcon) { // heliport.v3.api.channelSessionApi.updateMyProfile(_updateMyProfileCallback, m_Name, m_CircleIconURL, ""); m_UpdatedIcon = false; } // 多重での監視状態を防止するため、個人通知監視停止 heliport.v3.api.apiNotification.unWatchPersonal(); if (Islogin) { string VketLoginUserCode = "vketaccount__" + m_VketUserCode; heliport.v3.api.apiNotification.watchPersonal(VketLoginUserCode); } else { string VketGuestUserCode = m_VketUserCode; heliport.v3.api.apiNotification.watchPersonal(VketGuestUserCode); } // 初回入室処理を終わる if(m_IsFirstUpdate) { m_IsFirstUpdate = false; // プロフィールの初期化が終わったことを通知する hsCallCanvasComponentMethod("vcc_icon_only_base", "ChSBridge", "SetInitedProfile", "true"); // ゲストユーザーの場合、初回入室時にChS-APIの初期化が済んでおらず、初回名前の変更ができないので、入室ダイアログ押下時に改めて更新処理を行う if(!Islogin) { UpdateNickname(); return; } } // Profile画面の更新 m_ViewModel.UpdateViewDataByProfile(m_Name, m_Introduction, m_CircleIconURL, m_VketUserCode, ((Islogin)? "login" : "guest")); } void SetUserProfileState(bool Islogin) { JsVal val = makeJsObj(); val.AddPropertyByVal("user_code", makeJsStrFrom(m_VketUserCode)); val.AddPropertyByVal("user_type", makeJsStrFrom(((Islogin)? "login" : "guest"))); val.AddPropertyByVal("user_name", makeJsStrFrom(m_Name)); val.AddPropertyByVal("icon_url", makeJsStrFrom(m_CircleIconURL)); val.AddPropertyByVal("introduction", makeJsStrFrom(m_Introduction)); string UserProfile = val.ToString(); hsNetSetCustomState("UserProfile", UserProfile); // 初回プロフィール取得ではないならプロフィール更新データを送信する if(!m_IsFirstUpdate) { hsNetSendCustomData("UpdateUserProfile", UserProfile); } } public void UpdateNickname() { if(m_IsFirstUpdate) { FetchProfile(true, false); return; } string name = hel_get_skyway_username(); // 文字数が20文字より多いとAPIでエラーが出て後続の処理が実行されなくなるのでひとまずクライアント側で区切っておく name = name.SubString(0, 20); _UpdateProfile(name, m_Introduction); } public void UpdateIntroduction(string Introduction) { // 文字数が(おそらく)200文字より多いとAPIでエラーが出て後続の処理が実行されなくなるのでひとまずクライアント側で区切っておく Introduction = Introduction.SubString(0, 200); _UpdateProfile(m_Name, Introduction); } public void UpdateIcon() { heliport.v3.api.profiles.changeProfileIcon(_changeProfileIconCallback, m_VketUserCode, (m_CurrentSelfUserState == SELF_USER_STATE_GUEST)); } void _UpdateProfile(string Name, string Introduction) { if((m_CurrentSelfUserState == SELF_USER_STATE_GUEST)) { heliport.v3.api.profiles.updateGuestProfile(_UpdateProfileCallback, m_VketUserCode, Name, Introduction); } else { heliport.v3.api.profiles.updateProfile(_UpdateProfileCallback, Name, Introduction); } } void _UpdateProfileCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if (result.status == "ok") { heliport.v3.api.channelSessionApi.refreshChannelSession(_RefreshChannelSessionCallback); } else { bool Islogin = m_CurrentSelfUserState == SELF_USER_STATE_LOGIN; // Profile画面を変更前の状態に戻す m_ViewModel.UpdateViewDataByProfile(m_Name, m_Introduction, m_CircleIconURL, m_VketUserCode, ((Islogin) ? "login" : "guest")); } } void _changeProfileIconCallback() { m_UpdatedIcon = true; heliport.v3.api.channelSessionApi.refreshChannelSession(_RefreshChannelSessionCallback); } void _RefreshChannelSessionCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; FetchProfile(true, false); } void _updateMyProfileCallback(JsVal val) { ReturnType result = hsLoadReturnType(val); if(!result.IsValid()) return; } }