diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a01b18a57..a887a35fcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ if (USE_GLES AND (NOT ANDROID)) set(DISABLE_QML_OPTION ON) endif() + option(BUILD_CLIENT "Build client components" ${BUILD_CLIENT_OPTION}) option(BUILD_SERVER "Build server components" ${BUILD_SERVER_OPTION}) option(BUILD_TESTS "Build tests" ${BUILD_TESTS_OPTION}) @@ -162,7 +163,6 @@ if (BUILD_SERVER) set_target_properties(domain-server PROPERTIES FOLDER "Apps") add_subdirectory(ice-server) set_target_properties(ice-server PROPERTIES FOLDER "Apps") - add_subdirectory(server-console) endif() if (BUILD_CLIENT) @@ -174,6 +174,7 @@ endif() if (BUILD_CLIENT OR BUILD_SERVER) add_subdirectory(plugins) + add_subdirectory(server-console) endif() # BUILD_TOOLS option will be handled inside the tools's CMakeLists.txt because 'scribe' tool is required for build anyway diff --git a/cmake/macros/InstallBesideConsole.cmake b/cmake/macros/InstallBesideConsole.cmake index 3c991acf86..e3186501f4 100644 --- a/cmake/macros/InstallBesideConsole.cmake +++ b/cmake/macros/InstallBesideConsole.cmake @@ -66,8 +66,8 @@ macro(install_beside_console) install(CODE " set(MACOSX_BUNDLE_EXECUTABLE_NAME domain-server) set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.server-components) - set(MACOSX_BUNDLE_BUNDLE_NAME Sandbox\\ Components) - configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleSandboxComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist) + set(MACOSX_BUNDLE_BUNDLE_NAME Console\\ Components) + configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleConsoleComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist) execute_process(COMMAND ${MACDEPLOYQT_COMMAND} ${ESCAPED_BUNDLE_NAME} -verbose=2 -executable=${ESCAPED_EXECUTABLE_NAME})" COMPONENT ${SERVER_COMPONENT} ) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 0f8975e9b5..1b7243d4f2 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -18,7 +18,7 @@ macro(SET_PACKAGING_PARAMETERS) set(BUILD_GLOBAL_SERVICES "DEVELOPMENT") set(USE_STABLE_GLOBAL_SERVICES 0) set(BUILD_NUMBER 0) - set(APP_USER_MODEL_ID "com.highfidelity.sandbox-dev") + set(APP_USER_MODEL_ID "com.highfidelity.console-dev") set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV") set_from_env(RELEASE_NUMBER RELEASE_NUMBER "") @@ -37,6 +37,7 @@ macro(SET_PACKAGING_PARAMETERS) set(BUILD_VERSION ${RELEASE_NUMBER}) set(BUILD_ORGANIZATION "High Fidelity") set(HIGH_FIDELITY_PROTOCOL "hifi") + set(HIGH_FIDELITY_APP_PROTOCOL "hifiapp") set(INTERFACE_BUNDLE_NAME "Interface") set(INTERFACE_ICON_PREFIX "interface") @@ -142,7 +143,12 @@ macro(SET_PACKAGING_PARAMETERS) set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) - set(CONSOLE_EXEC_NAME "Sandbox.app") + if (CLIENT_ONLY) + set(CONSOLE_EXEC_NAME "Console.app") + else () + set(CONSOLE_EXEC_NAME "Sandbox.app") + endif() + set(CONSOLE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}") set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents") @@ -176,16 +182,19 @@ macro(SET_PACKAGING_PARAMETERS) # shortcut names if (PRODUCTION_BUILD) set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface") - set(CONSOLE_SHORTCUT_NAME "Sandbox") - set(APP_USER_MODEL_ID "com.highfidelity.sandbox") + set(CONSOLE_SHORTCUT_NAME "Console") + set(SANDBOX_SHORTCUT_NAME "Sandbox") + set(APP_USER_MODEL_ID "com.highfidelity.console") else () set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface - ${BUILD_VERSION_NO_SHA}") - set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}") + set(CONSOLE_SHORTCUT_NAME "Console - ${BUILD_VERSION_NO_SHA}") + set(SANDBOX_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}") endif () set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}") set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}") - + set(SANDBOX_HF_SHORTCUT_NAME "High Fidelity ${SANDBOX_SHORTCUT_NAME}") + set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity") set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console") diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in index a06fac092f..b9558cf361 100644 --- a/cmake/modules/MacOSXBundleInfo.plist.in +++ b/cmake/modules/MacOSXBundleInfo.plist.in @@ -42,6 +42,14 @@ hifi + + CFBundleURLName + ${MACOSX_BUNDLE_BUNDLE_NAME} APP URL + CFBundleURLSchemes + + hifiapp + + NSHighResolutionCapable diff --git a/cmake/templates/CPackProperties.cmake.in b/cmake/templates/CPackProperties.cmake.in index 1d7effd18f..cb6474b010 100644 --- a/cmake/templates/CPackProperties.cmake.in +++ b/cmake/templates/CPackProperties.cmake.in @@ -13,10 +13,12 @@ set(INTERFACE_DISPLAY_NAME "Interface") set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@") set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@") set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe") -set(CONSOLE_DISPLAY_NAME "Sandbox") +set(CONSOLE_DISPLAY_NAME "Console") set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@") set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@") set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_SHORTCUT_NAME@") +set(SANDBOX_SHORTCUT_NAME "@SANDBOX_SHORTCUT_NAME@") +set(SANDBOX_HF_SHORTCUT_NAME "@SANDBOX_HF_SHORTCUT_NAME@") set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@") set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@") set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@") @@ -25,6 +27,7 @@ set(DS_EXEC_NAME "@DS_EXEC_NAME@") set(AC_DISPLAY_NAME "Assignment Client") set(AC_EXEC_NAME "@AC_EXEC_NAME@") set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@") +set(HIGH_FIDELITY_APP_PROTOCOL "@HIGH_FIDELITY_APP_PROTOCOL@") set(PRODUCTION_BUILD "@PRODUCTION_BUILD@") set(PR_BUILD "@PR_BUILD@") set(BUILD_ORGANIZATION "@BUILD_ORGANIZATION@") diff --git a/cmake/templates/MacOSXBundleSandboxComponentsInfo.plist.in b/cmake/templates/MacOSXBundleConsoleComponentsInfo.plist.in similarity index 100% rename from cmake/templates/MacOSXBundleSandboxComponentsInfo.plist.in rename to cmake/templates/MacOSXBundleConsoleComponentsInfo.plist.in diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 7f6884f478..fd48a792dc 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -405,6 +405,14 @@ Var GAClientID Section "-Previous Install Cleanup" ; Remove the resources folder so we don't end up including removed QML files RMDir /r "$INSTDIR\resources" + + ; delete old assignment-client and domain-server so they're no longer present + ; in client only installs. + Delete "$INSTDIR\@DS_EXEC_NAME@" + Delete "$INSTDIR\@AC_EXEC_NAME@" + + ; delete interface so it's not there for server-only installs + Delete "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@" SectionEnd @CPACK_NSIS_INSTALLATION_TYPES@ @@ -532,9 +540,9 @@ SectionEnd Var PostInstallDialog Var DesktopClientCheckbox -Var DesktopServerCheckbox -Var ServerStartupCheckbox -Var LaunchServerNowCheckbox +Var DesktopConsoleCheckbox +Var ConsoleStartupCheckbox +Var LaunchConsoleNowCheckbox Var LaunchClientNowCheckbox Var CleanInstallCheckbox Var CurrentOffset @@ -747,32 +755,20 @@ Function PostInstallOptionsPage ${EndIf} ${If} @SERVER_COMPONENT_CONDITIONAL@ + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @SANDBOX_HF_SHORTCUT_NAME@" + ${Else} ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@" - Pop $DesktopServerCheckbox - IntOp $CurrentOffset $CurrentOffset + 15 - - ; set the checkbox state depending on what is present in the registry - !insertmacro SetInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED} - ${EndIf} - - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install" - Pop $LaunchServerNowCheckbox - - ; set the checkbox state depending on what is present in the registry - !insertmacro SetInstallOption $LaunchServerNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED} - ${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE - ${IfNot} $substringResult == "" - ${NSD_SetState} $LaunchServerNowCheckbox ${BST_UNCHECKED} - ${EndIf} - - IntOp $CurrentOffset $CurrentOffset + 15 ${EndIf} + + Pop $DesktopConsoleCheckbox + IntOp $CurrentOffset $CurrentOffset + 15 + ; set the checkbox state depending on what is present in the registry + !insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED} ${If} @CLIENT_COMPONENT_CONDITIONAL@ ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install" Pop $LaunchClientNowCheckbox - IntOp $CurrentOffset $CurrentOffset + 30 + IntOp $CurrentOffset $CurrentOffset + 15 ; set the checkbox state depending on what is present in the registry !insertmacro SetInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED} @@ -783,27 +779,44 @@ Function PostInstallOptionsPage ${EndIf} ${If} @SERVER_COMPONENT_CONDITIONAL@ - ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup" - Pop $ServerStartupCheckbox - IntOp $CurrentOffset $CurrentOffset + 15 - - ; set the checkbox state depending on what is present in the registry - !insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED} + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install" + ${Else} + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install" ${EndIf} + Pop $LaunchConsoleNowCheckbox + + ; set the checkbox state depending on what is present in the registry + !insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED} + ${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE + ${IfNot} $substringResult == "" + ${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED} + ${EndIf} + IntOp $CurrentOffset $CurrentOffset + 30 + + ${If} @SERVER_COMPONENT_CONDITIONAL@ + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup" + ${Else} + ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup" + ${EndIf} + Pop $ConsoleStartupCheckbox + IntOp $CurrentOffset $CurrentOffset + 15 + + ; set the checkbox state depending on what is present in the registry + !insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED} ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)" Pop $CleanInstallCheckbox IntOp $CurrentOffset $CurrentOffset + 15 ${If} @PR_BUILD@ == 1 - ; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked + ; a PR build defaults all install options expect LaunchConsoleNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked ${If} @CLIENT_COMPONENT_CONDITIONAL@ ${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED} ${EndIf} ${If} @SERVER_COMPONENT_CONDITIONAL@ - ${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED} - ${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED} + ${NSD_SetState} $DesktopConsoleCheckbox ${BST_UNCHECKED} + ${NSD_SetState} $ConsoleStartupCheckbox ${BST_UNCHECKED} ${EndIf} ; push the offset @@ -824,9 +837,9 @@ FunctionEnd !macroend Var DesktopClientState -Var DesktopServerState -Var ServerStartupState -Var LaunchServerNowState +Var DesktopConsoleState +Var ConsoleStartupState +Var LaunchConsoleNowState Var LaunchClientNowState Var CopyFromProductionState Var CleanInstallState @@ -842,11 +855,11 @@ Function ReadInstallTypes StrCpy $Express "1" StrCpy $DesktopClientState ${BST_CHECKED} - StrCpy $ServerStartupState ${BST_CHECKED} - StrCpy $LaunchServerNowState ${BST_CHECKED} + StrCpy $ConsoleStartupState ${BST_CHECKED} + StrCpy $LaunchConsoleNowState ${BST_CHECKED} StrCpy $LaunchClientNowState ${BST_CHECKED} StrCpy $CleanInstallState ${BST_UNCHECKED} - StrCpy $DesktopServerState ${BST_UNCHECKED} + StrCpy $DesktopConsoleState ${BST_UNCHECKED} ${If} @PR_BUILD@ == 1 StrCpy $CopyFromProductionState ${BST_UNCHECKED} @@ -860,28 +873,25 @@ Function ReadInstallTypes FunctionEnd Function ReadPostInstallOptions + + ; check if the user asked for a desktop shortcut to console + ${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState + + ; check if the user asked to have console launched every startup + ${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState + ${If} @CLIENT_COMPONENT_CONDITIONAL@ ; check if the user asked for a desktop shortcut to High Fidelity ${NSD_GetState} $DesktopClientCheckbox $DesktopClientState ${EndIf} - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ; check if the user asked for a desktop shortcut to Sandbox - ${NSD_GetState} $DesktopServerCheckbox $DesktopServerState - - ; check if the user asked to have Sandbox launched every startup - ${NSD_GetState} $ServerStartupCheckbox $ServerStartupState - ${EndIf} - ${If} @PR_BUILD@ == 1 ; check if we need to copy settings/content from production for this PR build ${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState ${EndIf} - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ; check if we need to launch the server post-install - ${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState - ${EndIf} + ; check if we need to launch the console post-install + ${NSD_GetState} $LaunchConsoleNowCheckbox $LaunchConsoleNowState ${If} @CLIENT_COMPONENT_CONDITIONAL@ ; check if we need to launch the client post-install @@ -893,6 +903,31 @@ Function ReadPostInstallOptions FunctionEnd Function HandlePostInstallOptions + + ${If} @SERVER_COMPONENT_CONDITIONAL@ + ; check if the user asked for a desktop shortcut to the console + ${If} $DesktopConsoleState == ${BST_CHECKED} + Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" + CreateShortCut "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" + !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES + ; Set appUserModelId + ApplicationID::Set "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@" + ${Else} + !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO + ${EndIf} + ${Else} + ; check if the user asked for a desktop shortcut to the console + ${If} $DesktopConsoleState == ${BST_CHECKED} + Delete "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" + CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" + !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES + ; Set appUserModelId + ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@" + ${Else} + !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO + ${EndIf} + ${EndIf} + ${If} @CLIENT_COMPONENT_CONDITIONAL@ ; check if the user asked for a desktop shortcut to High Fidelity ${If} $DesktopClientState == ${BST_CHECKED} @@ -901,38 +936,25 @@ Function HandlePostInstallOptions ${Else} !insertmacro WriteInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO ${EndIf} - ${EndIf} - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ; check if the user asked for a desktop shortcut to Sandbox - ${If} $DesktopServerState == ${BST_CHECKED} - CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" - !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES - ; Set appUserModelId - ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@" - ${Else} - !insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO - ${EndIf} + ; check if the user asked to have Console launched every startup + ${If} $ConsoleStartupState == ${BST_CHECKED} + ; in case we added a shortcut in the global context, pull that now + SetShellVarContext all + Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk" + ; make a startup shortcut in this user's current context + ; use the console shortcut name regardless of server/interface install + SetShellVarContext current + CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" - ; check if the user asked to have Sandbox launched every startup - ${If} $ServerStartupState == ${BST_CHECKED} - ; in case we added a shortcut in the global context, pull that now - SetShellVarContext all - Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk" + ; reset the shell var context back + SetShellVarContext all - ; make a startup shortcut in this user's current context - SetShellVarContext current - CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" - - ; reset the shell var context back - SetShellVarContext all - - !insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES - ${Else} - !insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO - ${EndIf} + !insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES + ${Else} + !insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO ${EndIf} ; check if the user asked for a clean install @@ -982,32 +1004,38 @@ Function HandlePostInstallOptions ${EndIf} ${EndIf} - ${If} @SERVER_COMPONENT_CONDITIONAL@ - ${AndIf} $LaunchServerNowState == ${BST_CHECKED} - !insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES - - ; both launches use the explorer trick in case the user has elevated permissions for the installer - ${If} $LaunchClientNowState == ${BST_CHECKED} + ${If} $LaunchClientNowState == ${BST_CHECKED} !insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES - ; create shortcut with ARGUMENTS - CreateShortCut "$TEMP\SandboxShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface" - Exec '"$WINDIR\explorer.exe" "$TEMP\SandboxShortcut.lnk"' - ${Else} + ${Else} !insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO + ${EndIf} + + ${If} $LaunchConsoleNowState == ${BST_CHECKED} + !insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES + ${Else} + !insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO + ${EndIf} + + ${If} $LaunchConsoleNowState == ${BST_CHECKED} + ${If} @SERVER_COMPONENT_CONDITIONAL@ + ${AndIf} $LaunchClientNowState == ${BST_CHECKED} + ${AndIf} @CLIENT_COMPONENT_CONDITIONAL@ + ; both launches use the explorer trick in case the user has elevated permissions for the installer + ; create shortcut with ARGUMENTS + CreateShortCut "$TEMP\ConsoleShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface" + Exec '"$WINDIR\explorer.exe" "$TEMP\ConsoleShortcut.lnk"' + ${Else} Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"' ${EndIf} + ${EndIf} - ${ElseIf} @CLIENT_COMPONENT_CONDITIONAL@ - !insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO - - ; launch uses the explorer trick in case the user has elevated permissions for the installer - ${If} $LaunchClientNowState == ${BST_CHECKED} - !insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES + ${If} $LaunchClientNowState == ${BST_CHECKED} + ${AndIf} @CLIENT_COMPONENT_CONDITIONAL@ + ${Unless} $LaunchConsoleNowState == ${BST_CHECKED} + ${OrUnless} @SERVER_COMPONENT_CONDITIONAL@ + ; launch uses the explorer trick in case the user has elevated permissions for the installer Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"' - ${Else} - !insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO ${EndIf} - ${EndIf} FunctionEnd @@ -1164,8 +1192,16 @@ Section "-Core installation" ${EndIf} - ; Conditional handling for server console shortcut ${If} @SERVER_COMPONENT_CONDITIONAL@ + ; handling for server console shortcut + Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" \ + "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" + ; Set appUserModelId + ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@" + ${Else} + ; handling for interface only console shortcut + Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \ "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" ; Set appUserModelId @@ -1376,12 +1412,15 @@ Section "Uninstall" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk" Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" + Delete "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" ; if it exists, delete the startup shortcut for the current user SetShellVarContext current Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" + Delete "$SMSTARTUP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" SetShellVarContext all @CPACK_NSIS_DELETE_ICONS@ @@ -1414,6 +1453,7 @@ Section "Uninstall" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk" @CPACK_NSIS_DELETE_ICONS_EXTRA@ ;Delete empty start menu parent diretories diff --git a/server-console/CMakeLists.txt b/server-console/CMakeLists.txt index 1c6e40c582..49742cacf0 100644 --- a/server-console/CMakeLists.txt +++ b/server-console/CMakeLists.txt @@ -4,13 +4,17 @@ if (PRODUCTION_BUILD) set(PRODUCTION_OPTION "--production") endif() +if (CLIENT_ONLY) + set(CLIENT_ONLY_OPTION "--client_only") +endif() + # add a target that will package the console add_custom_target(${TARGET_NAME}-npm-install COMMAND npm install WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target(${TARGET_NAME} - COMMAND npm run packager -- --out ${CMAKE_CURRENT_BINARY_DIR} ${PRODUCTION_OPTION} + COMMAND npm run packager -- --out ${CMAKE_CURRENT_BINARY_DIR} ${PRODUCTION_OPTION} ${CLIENT_ONLY_OPTION} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${TARGET_NAME}-npm-install ) @@ -19,11 +23,21 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Server Console") set_target_properties(${TARGET_NAME}-npm-install PROPERTIES FOLDER "hidden/Server Console") # add a dependency from the package target to the server components -add_dependencies(${TARGET_NAME} assignment-client domain-server) +if (BUILD_CLIENT) + add_dependencies(${TARGET_NAME} interface) +endif() + +if (BUILD_SERVER) + add_dependencies(${TARGET_NAME} assignment-client domain-server) +endif() # set the packaged console folder depending on platform, so we can copy it if (APPLE) - set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}") + if (CLIENT_ONLY) + set(PACKAGED_CONSOLE_FOLDER "Console-darwin-x64/${CONSOLE_EXEC_NAME}") + else () + set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}") + endif() elseif (WIN32) set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64") elseif (UNIX) @@ -33,9 +47,9 @@ endif () # install the packaged Server Console in our install directory if (APPLE) install( - PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}" + DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}" + USE_SOURCE_PERMISSIONS DESTINATION ${CONSOLE_INSTALL_DIR} - COMPONENT ${SERVER_COMPONENT} ) elseif (WIN32) set(CONSOLE_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}") @@ -43,7 +57,6 @@ elseif (WIN32) install( DIRECTORY "${CONSOLE_DESTINATION}/" DESTINATION ${CONSOLE_INSTALL_DIR} - COMPONENT ${SERVER_COMPONENT} ) # sign the copied server console executable after install diff --git a/server-console/package.json b/server-console/package.json index 565658702b..b0d181c65a 100644 --- a/server-console/package.json +++ b/server-console/package.json @@ -1,6 +1,6 @@ { - "name": "HighFidelitySandbox", - "description": "High Fidelity Sandbox", + "name": "HighFidelityConsole", + "description": "High Fidelity Console", "author": "High Fidelity", "license": "Apache-2.0", "version": "1.0.0", diff --git a/server-console/packager.js b/server-console/packager.js index 89bcd7cb71..00866ee1be 100644 --- a/server-console/packager.js +++ b/server-console/packager.js @@ -27,8 +27,8 @@ var options = { } const EXEC_NAME = "server-console"; -const SHORT_NAME = "Sandbox"; -const FULL_NAME = "High Fidelity Sandbox"; +var SHORT_NAME = argv.client_only ? "Console" : "Sandbox"; +var FULL_NAME = argv.client_only ? "High Fidelity Console" : "High Fidelity Sandbox"; // setup per OS options if (osType == "Darwin") { diff --git a/server-console/src/main.js b/server-console/src/main.js index 95b5935255..c26938745b 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -60,7 +60,10 @@ const HOME_CONTENT_URL = "http://cdn.highfidelity.com/content-sets/home-tutorial const buildInfo = GetBuildInfo(); - +const NotificationState = { + UNNOTIFIED: 'unnotified', + NOTIFIED: 'notified' +}; // Update lock filepath const UPDATER_LOCK_FILENAME = ".updating"; @@ -104,12 +107,21 @@ userConfig.load(configPath); const ipcMain = electron.ipcMain; -function isServerInstalled() { - return interfacePath && userConfig.get("serverInstalled", true); +function isInterfaceInstalled () { + if (osType == "Darwin") { + // In OSX Sierra, the app translocation process moves + // the executable to a random location before starting it + // which makes finding the interface near impossible using + // relative paths. For now, as there are no server-only + // installs, we just assume the interface is installed here + return true; + } else { + return interfacePath; + } } -function isInterfaceInstalled() { - return dsPath && acPath && userConfig.get("interfaceInstalled", true); +function isServerInstalled () { + return dsPath && acPath; } var isShuttingDown = false; @@ -259,10 +271,14 @@ var debug = argv.debug; var binaryType = argv.binaryType; -interfacePath = pathFinder.discoveredPath("Interface", binaryType, buildInfo.releaseType); +interfacePath = pathFinder.discoveredPath("interface", binaryType, buildInfo.releaseType); dsPath = pathFinder.discoveredPath("domain-server", binaryType, buildInfo.releaseType); acPath = pathFinder.discoveredPath("assignment-client", binaryType, buildInfo.releaseType); +console.log("Domain Server Path: " + dsPath); +console.log("Assignment Client Path: " + acPath); +console.log("Interface Path: " + interfacePath); + function binaryMissingMessage(displayName, executableName, required) { var message = "The " + displayName + " executable was not found.\n"; @@ -286,18 +302,6 @@ function binaryMissingMessage(displayName, executableName, required) { return message; } -// if at this point any of the paths are null, we're missing something we wanted to find - -if (!dsPath) { - dialog.showErrorBox("Domain Server Not Found", binaryMissingMessage("domain-server", "domain-server", true)); - app.exit(0); -} - -if (!acPath) { - dialog.showErrorBox("Assignment Client Not Found", binaryMissingMessage("assignment-client", "assignment-client", true)); - app.exit(0); -} - function openFileBrowser(path) { // Add quotes around path path = '"' + path + '"'; @@ -332,12 +336,21 @@ const HifiNotifications = hfNotifications.HifiNotifications; const HifiNotificationType = hfNotifications.NotificationType; var pendingNotifications = {} -function notificationCallback(notificationType, pending = true) { +var notificationState = NotificationState.UNNOTIFIED; + +function setNotificationState (notificationType, pending = true) { pendingNotifications[notificationType] = pending; + notificationState = NotificationState.UNNOTIFIED; + for (var key in pendingNotifications) { + if (pendingNotifications[key]) { + notificationState = NotificationState.NOTIFIED; + break; + } + } updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); } -var trayNotifications = new HifiNotifications(userConfig, notificationCallback); +var trayNotifications = new HifiNotifications(userConfig, setNotificationState); var LogWindow = function(ac, ds) { this.ac = ac; @@ -373,7 +386,7 @@ LogWindow.prototype = { }; function visitSandboxClicked() { - if (interfacePath) { + if (isInterfaceInstalled()) { StartInterface('hifi://localhost'); } else { // show an error to say that we can't go home without an interface instance @@ -397,7 +410,7 @@ var labels = { type: 'checkbox', checked: true, click: function () { - trayNotifications.enable(!trayNotifications.enabled(), notificationCallback); + trayNotifications.enable(!trayNotifications.enabled(), setNotificationState); userConfig.save(configPath); updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); } @@ -406,32 +419,28 @@ var labels = { label: 'GoTo', click: function () { StartInterface("hifiapp:GOTO"); - pendingNotifications[HifiNotificationType.GOTO] = false; - updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); + setNotificationState(HifiNotificationType.GOTO, false); } }, people: { label: 'People', click: function () { StartInterface("hifiapp:PEOPLE"); - pendingNotifications[HifiNotificationType.PEOPLE] = false; - updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); + setNotificationState(HifiNotificationType.PEOPLE, false); } }, wallet: { label: 'Wallet', click: function () { StartInterface("hifiapp:WALLET"); - pendingNotifications[HifiNotificationType.WALLET] = false; - updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); + setNotificationState(HifiNotificationType.WALLET, false); } }, marketplace: { label: 'Market', click: function () { StartInterface("hifiapp:MARKET"); - pendingNotifications[HifiNotificationType.MARKETPLACE] = false; - updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); + setNotificationState(HifiNotificationType.MARKETPLACE, false); } }, restart: { @@ -517,11 +526,13 @@ function buildMenuArray(serverState) { menuArray.push(labels.share); menuArray.push(separator); if (isInterfaceInstalled()) { - menuArray.push(labels.goto); - menuArray.push(labels.people); - menuArray.push(labels.wallet); - menuArray.push(labels.marketplace); - menuArray.push(separator); + if (trayNotifications.enabled()) { + menuArray.push(labels.goto); + menuArray.push(labels.people); + menuArray.push(labels.wallet); + menuArray.push(labels.marketplace); + menuArray.push(separator); + } menuArray.push(labels.showNotifications); menuArray.push(separator); } @@ -553,10 +564,6 @@ function updateLabels(serverState) { } labels.showNotifications.checked = trayNotifications.enabled(); - labels.people.visible = trayNotifications.enabled(); - labels.goto.visible = trayNotifications.enabled(); - labels.wallet.visible = trayNotifications.enabled(); - labels.marketplace.visible = trayNotifications.enabled(); labels.goto.icon = pendingNotifications[HifiNotificationType.GOTO] ? menuNotificationIcon : null; labels.people.icon = pendingNotifications[HifiNotificationType.PEOPLE] ? menuNotificationIcon : null; labels.wallet.icon = pendingNotifications[HifiNotificationType.WALLET] ? menuNotificationIcon : null; @@ -567,7 +574,7 @@ function updateLabels(serverState) { function updateTrayMenu(serverState) { if (tray) { var menuArray = buildMenuArray(isShuttingDown ? null : serverState); - tray.setImage(trayIcons[serverState]); + tray.setImage(trayIcons[notificationState]); tray.setContextMenu(Menu.buildFromTemplate(menuArray)); if (isShuttingDown) { tray.setToolTip('High Fidelity - Shutting Down'); @@ -787,9 +794,8 @@ function maybeShowSplash() { const trayIconOS = (osType == "Darwin") ? "osx" : "win"; var trayIcons = {}; -trayIcons[ProcessGroupStates.STARTED] = "console-tray-" + trayIconOS + ".png"; -trayIcons[ProcessGroupStates.STOPPED] = "console-tray-" + trayIconOS + "-stopped.png"; -trayIcons[ProcessGroupStates.STOPPING] = "console-tray-" + trayIconOS + "-stopping.png"; +trayIcons[NotificationState.UNNOTIFIED] = "console-tray-" + trayIconOS + ".png"; +trayIcons[NotificationState.NOTIFIED] = "console-tray-" + trayIconOS + "-stopped.png"; for (var key in trayIcons) { var fullPath = path.join(__dirname, '../resources/' + trayIcons[key]); var img = nativeImage.createFromPath(fullPath); @@ -815,33 +821,33 @@ function onContentLoaded() { // Disable splash window for now. // maybeShowSplash(); - if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) { - - const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30; - var hasShownUpdateNotification = false; - const updateChecker = new updater.UpdateChecker(buildInfo, CHECK_FOR_UPDATES_INTERVAL_SECONDS); - updateChecker.on('update-available', function(latestVersion, url) { - if (!hasShownUpdateNotification) { - notifier.notify({ - icon: notificationIcon, - title: 'An update is available!', - message: 'High Fidelity version ' + latestVersion + ' is available', - wait: true, - appID: buildInfo.appUserModelId, - url: url - }); - hasShownUpdateNotification = true; - } - }); - notifier.on('click', function(notifierObject, options) { - log.debug("Got click", options.url); - shell.openExternal(options.url); - }); - } - - deleteOldFiles(logPath, DELETE_LOG_FILES_OLDER_THAN_X_SECONDS, LOG_FILE_REGEX); - if (isServerInstalled()) { + if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) { + + const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30; + var hasShownUpdateNotification = false; + const updateChecker = new updater.UpdateChecker(buildInfo, CHECK_FOR_UPDATES_INTERVAL_SECONDS); + updateChecker.on('update-available', function(latestVersion, url) { + if (!hasShownUpdateNotification) { + notifier.notify({ + icon: notificationIcon, + title: 'An update is available!', + message: 'High Fidelity version ' + latestVersion + ' is available', + wait: true, + appID: buildInfo.appUserModelId, + url: url + }); + hasShownUpdateNotification = true; + } + }); + notifier.on('click', function(notifierObject, options) { + log.debug("Got click", options.url); + shell.openExternal(options.url); + }); + } + + deleteOldFiles(logPath, DELETE_LOG_FILES_OLDER_THAN_X_SECONDS, LOG_FILE_REGEX); + var dsArguments = ['--get-temp-name', '--parent-pid', process.pid]; domainServer = new Process('domain-server', dsPath, dsArguments, logPath); @@ -902,13 +908,16 @@ app.on('ready', function() { } // Create tray icon - tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]); + tray = new Tray(trayIcons[NotificationState.UNNOTIFIED]); tray.setToolTip('High Fidelity'); tray.on('click', function() { tray.popUpContextMenu(tray.menu); }); + if (isInterfaceInstalled()) { + trayNotifications.startPolling(); + } updateTrayMenu(ProcessGroupStates.STOPPED); maybeInstallDefaultContentSet(onContentLoaded); diff --git a/server-console/src/modules/hf-acctinfo.js b/server-console/src/modules/hf-acctinfo.js index 828bc781b8..d20748544f 100644 --- a/server-console/src/modules/hf-acctinfo.js +++ b/server-console/src/modules/hf-acctinfo.js @@ -66,7 +66,7 @@ AccountInfo.prototype = { case VariantTypes.USER_TYPE: //user type var userTypeName = this._parseByteArray().toString('ascii').slice(0,-1); - if (userTypeName == "DataServerAccountInfo") { + if (userTypeName === "DataServerAccountInfo") { return this._parseDataServerAccountInfo(); } else { @@ -77,7 +77,7 @@ AccountInfo.prototype = { }, _parseByteArray: function () { var length = this._parseUInt32(); - if (length == 0xffffffff) { + if (length === 0xffffffff) { return null; } var result = this.rawData.slice(this.parseOffset, this.parseOffset+length); @@ -91,7 +91,7 @@ AccountInfo.prototype = { } // length in bytes; var length = this._parseUInt32(); - if (length == 0xFFFFFFFF) { + if (length === 0xFFFFFFFF) { return null; } diff --git a/server-console/src/modules/hf-app.js b/server-console/src/modules/hf-app.js index 625715b392..af6c38cdb3 100644 --- a/server-console/src/modules/hf-app.js +++ b/server-console/src/modules/hf-app.js @@ -7,6 +7,7 @@ const path = require('path'); const argv = require('yargs').argv; const hfprocess = require('./hf-process'); const osHomeDir = require('os-homedir'); +const childProcess = require('child_process'); const Process = hfprocess.Process; const binaryType = argv.binaryType; @@ -15,9 +16,9 @@ const osType = os.type(); exports.getBuildInfo = function() { var buildInfoPath = null; - if (osType == 'Windows_NT') { + if (osType === 'Windows_NT') { buildInfoPath = path.join(path.dirname(process.execPath), 'build-info.json'); - } else if (osType == 'Darwin') { + } else if (osType === 'Darwin') { var contentPath = ".app/Contents/"; var contentEndIndex = __dirname.indexOf(contentPath); @@ -34,7 +35,7 @@ exports.getBuildInfo = function() { buildNumber: "0", stableBuild: "0", organization: "High Fidelity - dev", - appUserModelId: "com.highfidelity.sandbox-dev" + appUserModelId: "com.highfidelity.console" }; var buildInfo = DEFAULT_BUILD_INFO; @@ -50,37 +51,59 @@ exports.getBuildInfo = function() { } const buildInfo = exports.getBuildInfo(); -const interfacePath = pathFinder.discoveredPath("Interface", binaryType, buildInfo.releaseType); +const interfacePath = pathFinder.discoveredPath("interface", binaryType, buildInfo.releaseType); exports.startInterface = function(url) { - var argArray = []; - // check if we have a url parameter to include - if (url) { - argArray = ["--url", url]; + if (osType === 'Darwin') { + if (!url) { + log.debug("No URL given for startInterface"); + return; + } + + // do this as a workaround for app translocation on osx, which makes + // it nearly impossible to find the interface executable + var bundle_id = 'com.highfidelity.interface-dev'; + if (buildInfo.releaseType == 'PR') { + bundle_id = 'com.highfidelity.interface-pr'; + } else if (buildInfo.releaseType == 'PRODUCTION') { + bundle_id = 'com.highfidelity.interface'; + } + childProcess.exec('open -b ' + bundle_id + ' --args --url ' + url); + } else { + var argArray = []; + + // check if we have a url parameter to include + if (url) { + argArray = ["--url", url]; + } + console.log("Starting with " + url); + // create a new Interface instance - Interface makes sure only one is running at a time + var pInterface = new Process('Interface', interfacePath, argArray); + pInterface.detached = true; + pInterface.start(); } - console.log("Starting with " + url); - // create a new Interface instance - Interface makes sure only one is running at a time - var pInterface = new Process('Interface', interfacePath, argArray); - pInterface.detached = true; - pInterface.start(); } exports.isInterfaceRunning = function(done) { - var pInterface = new Process('interface', 'interface.exe'); + if (osType === 'Windows_NT') { + var pInterface = new Process('interface', 'interface.exe'); + } else if (osType === 'Darwin') { + var pInterface = new Process('interface', 'interface'); + } return pInterface.isRunning(done); } exports.getRootHifiDataDirectory = function(local) { var organization = buildInfo.organization; - if (osType == 'Windows_NT') { + if (osType === 'Windows_NT') { if (local) { return path.resolve(osHomeDir(), 'AppData/Local', organization); } else { return path.resolve(osHomeDir(), 'AppData/Roaming', organization); } - } else if (osType == 'Darwin') { + } else if (osType === 'Darwin') { return path.resolve(osHomeDir(), 'Library/Application Support', organization); } else { return path.resolve(osHomeDir(), '.local/share/', organization); diff --git a/server-console/src/modules/hf-notifications.js b/server-console/src/modules/hf-notifications.js index 281ca1cb53..464d268c5e 100644 --- a/server-console/src/modules/hf-notifications.js +++ b/server-console/src/modules/hf-notifications.js @@ -7,12 +7,15 @@ const path = require('path'); const AccountInfo = require('./hf-acctinfo').AccountInfo; const GetBuildInfo = hfApp.getBuildInfo; const buildInfo = GetBuildInfo(); +const osType = os.type(); const notificationIcon = path.join(__dirname, '../../resources/console-notification.png'); const STORIES_NOTIFICATION_POLL_TIME_MS = 120 * 1000; const PEOPLE_NOTIFICATION_POLL_TIME_MS = 120 * 1000; const WALLET_NOTIFICATION_POLL_TIME_MS = 600 * 1000; const MARKETPLACE_NOTIFICATION_POLL_TIME_MS = 600 * 1000; +const OSX_CLICK_DELAY_TIMEOUT = 500; + const METAVERSE_SERVER_URL= process.env.HIFI_METAVERSE_URL ? process.env.HIFI_METAVERSE_URL : 'https://metaverse.highfidelity.com' const STORIES_URL= '/api/v1/user_stories'; @@ -33,21 +36,22 @@ const NotificationType = { MARKETPLACE: 'marketplace' }; + function HifiNotification(notificationType, notificationData, menuNotificationCallback) { this.type = notificationType; this.data = notificationData; } HifiNotification.prototype = { - show: function () { + show: function (finished) { var text = ""; var message = ""; var url = null; var app = null; switch (this.type) { case NotificationType.GOTO: - if (typeof(this.data) == "number") { - if (this.data == 1) { + if (typeof(this.data) === "number") { + if (this.data === 1) { text = "You have " + this.data + " event invitation pending." } else { text = "You have " + this.data + " event invitations pending." @@ -62,8 +66,8 @@ HifiNotification.prototype = { break; case NotificationType.PEOPLE: - if (typeof(this.data) == "number") { - if (this.data == 1) { + if (typeof(this.data) === "number") { + if (this.data === 1) { text = this.data + " of your connections is online." } else { text = this.data + " of your connections are online." @@ -78,8 +82,8 @@ HifiNotification.prototype = { break; case NotificationType.WALLET: - if (typeof(this.data) == "number") { - if (this.data == 1) { + if (typeof(this.data) === "number") { + if (this.data === 1) { text = "You have " + this.data + " unread Wallet transaction."; } else { text = "You have " + this.data + " unread Wallet transactions."; @@ -94,8 +98,8 @@ HifiNotification.prototype = { break; case NotificationType.MARKETPLACE: - if (typeof(this.data) == "number") { - if (this.data == 1) { + if (typeof(this.data) === "number") { + if (this.data === 1) { text = this.data + " of your purchased items has an update available."; } else { text = this.data + " of your purchased items have updates available."; @@ -114,8 +118,18 @@ HifiNotification.prototype = { message: message, wait: true, appID: buildInfo.appUserModelId, - url: url - }); + url: url, + timeout: 5 + }, + function (error, reason, metadata) { + if (finished) { + if (osType === 'Darwin') { + setTimeout(finished, OSX_CLICK_DELAY_TIMEOUT); + } else { + finished(); + } + } + }); } } @@ -128,7 +142,8 @@ function HifiNotifications(config, menuNotificationCallback) { this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z")); this.marketplaceSince = new Date(this.config.get("marketplaceNotifySince", "1970-01-01T00:00:00.000Z")); - this.enable(this.enabled()); + this.pendingNotifications = []; + var _menuNotificationCallback = menuNotificationCallback; notifier.on('click', function (notifierObject, options) { @@ -139,7 +154,7 @@ function HifiNotifications(config, menuNotificationCallback) { HifiNotifications.prototype = { enable: function (enabled) { - this.config.set("enableTrayNotifications", enabled); + this.config.set("disableTrayNotifications", !enabled); if (enabled) { var _this = this; this.storiesPollTimer = setInterval(function () { @@ -170,22 +185,14 @@ HifiNotifications.prototype = { }, MARKETPLACE_NOTIFICATION_POLL_TIME_MS); } else { - if (this.storiesPollTimer) { - clearInterval(this.storiesPollTimer); - } - if (this.peoplePollTimer) { - clearInterval(this.peoplePollTimer); - } - if (this.walletPollTimer) { - clearInterval(this.walletPollTimer); - } - if (this.marketplacePollTimer) { - clearInterval(this.marketplacePollTimer); - } + this.stopPolling(); } }, enabled: function () { - return this.config.get("enableTrayNotifications", true); + return !this.config.get("disableTrayNotifications", false); + }, + startPolling: function () { + this.enable(this.enabled()); }, stopPolling: function () { this.config.set("storiesNotifySince", this.storiesSince.toISOString()); @@ -193,7 +200,48 @@ HifiNotifications.prototype = { this.config.set("walletNotifySince", this.walletSince.toISOString()); this.config.set("marketplaceNotifySince", this.marketplaceSince.toISOString()); - this.enable(false); + if (this.storiesPollTimer) { + clearInterval(this.storiesPollTimer); + } + if (this.peoplePollTimer) { + clearInterval(this.peoplePollTimer); + } + if (this.walletPollTimer) { + clearInterval(this.walletPollTimer); + } + if (this.marketplacePollTimer) { + clearInterval(this.marketplacePollTimer); + } + }, + _showNotification: function () { + var _this = this; + + if (osType === 'Darwin') { + this.pendingNotifications[0].show(function () { + // For OSX + // Don't attempt to show the next notification + // until the current is clicked or times out + // as the OSX Notifier stuff will dismiss the + // previous notification immediately when a + // new one is submitted + _this.pendingNotifications.shift(); + if(_this.pendingNotifications.length > 0) { + _this._showNotification(); + } + }); + } else { + // For Windows + // All notifications are sent immediately as they are queued + // by windows in Tray Notifications and can be bulk seen and + // dismissed + _this.pendingNotifications.shift().show(); + } + }, + _addNotification: function (notification) { + this.pendingNotifications.push(notification); + if (this.pendingNotifications.length === 1) { + this._showNotification(); + } }, _pollToDisableHighlight: function (notifyType, error, data) { if (error || !data.body) { @@ -248,8 +296,7 @@ HifiNotifications.prototype = { } _this.menuNotificationCallback(notifyType, true); if (content.total_entries >= maxNotificationItemCount) { - var notification = new HifiNotification(notifyType, content.total_entries); - notification.show(); + _this._addNotification(new HifiNotification(notifyType, content.total_entries)); } else { var notifyData = [] switch (notifyType) { @@ -268,8 +315,7 @@ HifiNotifications.prototype = { } notifyData.forEach(function (notifyDataEntry) { - var notification = new HifiNotification(notifyType, notifyDataEntry); - notification.show(); + _this._addNotification(new HifiNotification(notifyType, notifyDataEntry)); }); } finished(true, token); @@ -376,13 +422,11 @@ HifiNotifications.prototype = { } if (newUsers.size >= maxNotificationItemCount) { - var notification = new HifiNotification(NotificationType.PEOPLE, newUsers.size); - notification.show(); + _this._addNotification(new HifiNotification(NotificationType.PEOPLE, newUsers.size)); return; } newUsers.forEach(function (user) { - var notification = new HifiNotification(NotificationType.PEOPLE, user); - notification.show(); + _this._addNotification(new HifiNotification(NotificationType.PEOPLE, user)); }); }); }); diff --git a/server-console/src/modules/hf-process.js b/server-console/src/modules/hf-process.js index cf94ec6b29..7736de0e55 100644 --- a/server-console/src/modules/hf-process.js +++ b/server-console/src/modules/hf-process.js @@ -274,7 +274,9 @@ Process.prototype = extend(Process.prototype, { done(running); }); } else if (os.type == 'Darwin') { - console.log("TODO IsRunning Darwin"); + childProcess.exec('ps cax | grep ' + _command, function (err, stdout, stderr) { + done(stdout.length > 0); + }); } }, diff --git a/server-console/src/modules/path-finder.js b/server-console/src/modules/path-finder.js index 5ecd2c74ff..a7ccee2631 100644 --- a/server-console/src/modules/path-finder.js +++ b/server-console/src/modules/path-finder.js @@ -1,8 +1,9 @@ var fs = require('fs'); var path = require('path'); +const { app } = require('electron'); function platformExtension(name) { - if (name == "Interface") { + if (name == "interface") { if (process.platform == "darwin") { return ".app/Contents/MacOS/" + name } else if (process.platform == "win32") { @@ -53,9 +54,9 @@ exports.searchPaths = function(name, binaryType, releaseType) { var componentsPath = appPath + "/Contents/MacOS/Components.app/Contents/MacOS/"; paths.push(componentsPath + name + extension); - // check beside the app bundle for the binaries - paths.push(path.join(path.dirname(appPath), name + extension)); } + // check beside the app bundle for the binaries + paths.push(path.join(path.dirname(app.getAppPath()), "../../..", name + extension)); } }