[RAPPS] Refresh item info after installer completes (#7697)

- Refresh the details view of the item that was just installed.
- Hint update of uninstallers list is needed.
- Restore focus correctly after installer process finishes.

CORE-17677
This commit is contained in:
Whindmar Saksit 2025-02-07 21:33:19 +01:00 committed by GitHub
parent a610016952
commit 5bc6d59142
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 109 additions and 29 deletions

View file

@ -10,6 +10,14 @@
#include "rapps.h" #include "rapps.h"
#include "appview.h" #include "appview.h"
static inline AppsCategories
ClampAvailableCategory(AppsCategories Category)
{
if (Category <= ENUM_LASTCATEGORY)
return Category;
return ENUM_CAT_OTHER; // Treat future categories we don't know as Other
}
CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category) CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category)
: szIdentifier(Identifier), iCategory(Category) : szIdentifier(Identifier), iCategory(Category)
{ {
@ -24,7 +32,7 @@ CAvailableApplicationInfo::CAvailableApplicationInfo(
const CStringW &PkgName, const CStringW &PkgName,
AppsCategories Category, AppsCategories Category,
const CPathW &BasePath) const CPathW &BasePath)
: CAppInfo(PkgName, Category), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false) : CAppInfo(PkgName, ClampAvailableCategory(Category)), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false)
{ {
m_Parser->GetString(L"Name", szDisplayName); m_Parser->GetString(L"Name", szDisplayName);
m_Parser->GetString(L"Version", szDisplayVersion); m_Parser->GetString(L"Version", szDisplayVersion);
@ -588,7 +596,7 @@ CInstalledApplicationInfo::GetInstallerType() const
BOOL BOOL
CInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags) CInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags)
{ {
if (GetInstallerType() == INSTALLER_GENERATE) if (GetInstallerType() == INSTALLER_GENERATE && (Flags & UCF_SAMEPROCESS))
{ {
return UninstallGenerated(*this, Flags); return UninstallGenerated(*this, Flags);
} }

View file

@ -955,19 +955,22 @@ CAppInfoDisplay::Create(HWND hwndParent)
} }
VOID VOID
CAppInfoDisplay::ShowAppInfo(CAppInfo *Info) CAppInfoDisplay::ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText)
{ {
CStringW ScrnshotLocation; if (!OnlyUpdateText)
if (Info->RetrieveScreenshot(ScrnshotLocation))
{ {
ScrnshotPrev->DisplayImage(ScrnshotLocation); CStringW ScrnshotLocation;
} if (Info.RetrieveScreenshot(ScrnshotLocation))
else {
{ ScrnshotPrev->DisplayImage(ScrnshotLocation);
ScrnshotPrev->DisplayEmpty(); }
else
{
ScrnshotPrev->DisplayEmpty();
}
} }
ResizeChildren(); ResizeChildren();
Info->ShowAppInfo(RichEdit); Info.ShowAppInfo(RichEdit);
} }
void void
@ -1805,6 +1808,22 @@ CApplicationView::SetRedraw(BOOL bRedraw)
m_ListView->SetRedraw(bRedraw); m_ListView->SetRedraw(bRedraw);
} }
void
CApplicationView::RefreshAvailableItem(PCWSTR PackageName)
{
if (ApplicationViewType != AppViewTypeAvailableApps || !PackageName)
return;
CAppInfo *pApp;
for (UINT i = 0; (pApp = (CAppInfo*)m_ListView->GetItemData(i)) != NULL; ++i)
{
if (pApp->szIdentifier.CompareNoCase(PackageName) == 0)
{
RefreshDetailsPane(*pApp, true);
break;
}
}
}
void void
CApplicationView::SetFocusOnSearchBar() CApplicationView::SetFocusOnSearchBar()
{ {
@ -2134,6 +2153,12 @@ CApplicationView::RestoreListSelection(const RESTORELISTSELECTION &Restore)
} }
} }
VOID
CApplicationView::RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText)
{
m_AppsInfo->ShowAppInfo(Info, OnlyUpdateText);
}
// this function is called when a item of listview get focus. // this function is called when a item of listview get focus.
// CallbackParam is the param passed to listview when adding the item (the one getting focus now). // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
VOID VOID
@ -2142,7 +2167,7 @@ CApplicationView::ItemGetFocus(LPVOID CallbackParam)
if (CallbackParam) if (CallbackParam)
{ {
CAppInfo *Info = static_cast<CAppInfo *>(CallbackParam); CAppInfo *Info = static_cast<CAppInfo *>(CallbackParam);
m_AppsInfo->ShowAppInfo(Info); RefreshDetailsPane(*Info);
if (ApplicationViewType == AppViewTypeInstalledApps) if (ApplicationViewType == AppViewTypeInstalledApps)
{ {

View file

@ -81,6 +81,8 @@ CSideTreeView::~CSideTreeView()
// **** CSideTreeView **** // **** CSideTreeView ****
// **** CMainWindow **** // **** CMainWindow ****
HWND CMainWindow::m_hLastFocus = NULL;
bool CMainWindow::m_PendingInstalledViewRefresh = false;
CMainWindow::CMainWindow(CAppDB *db, BOOL bAppwiz) : m_ClientPanel(NULL), m_Db(db), m_bAppwizMode(bAppwiz), SelectedEnumType(ENUM_ALL_INSTALLED) CMainWindow::CMainWindow(CAppDB *db, BOOL bAppwiz) : m_ClientPanel(NULL), m_Db(db), m_bAppwizMode(bAppwiz), SelectedEnumType(ENUM_ALL_INSTALLED)
{ {
@ -343,10 +345,32 @@ CMainWindow::ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lPa
SendMessage(WM_CLOSE, 0, 0); SendMessage(WM_CLOSE, 0, 0);
break; break;
case WM_NOTIFY_INSTALLERFINISHED:
m_PendingInstalledViewRefresh = true; // Something just installed, our uninstall list is probably outdated
m_ApplicationView->RefreshAvailableItem((PCWSTR)lParam);
break;
case DM_REPOSITION: case DM_REPOSITION:
EmulateDialogReposition(hwnd); // We are not a real dialog, we need help from a real one EmulateDialogReposition(hwnd); // We are not a real dialog, we need help from a real one
break; break;
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE)
m_hLastFocus = ::GetFocus();
break;
case WM_SETFOCUS:
if (m_hLastFocus)
::SetFocus(m_hLastFocus);
break;
case WM_NEXTDLGCTL:
if (!LOWORD(lParam))
HandleTabOrder(wParam ? -1 : 1);
else if (wParam)
::SetFocus((HWND)wParam);
break;
case WM_COMMAND: case WM_COMMAND:
OnCommand(wParam, lParam); OnCommand(wParam, lParam);
break; break;
@ -678,6 +702,12 @@ CMainWindow::UpdateApplicationsList(AppsCategories EnumType, BOOL bReload, BOOL
if (bCheckAvailable) if (bCheckAvailable)
CheckAvailable(); CheckAvailable();
if (m_PendingInstalledViewRefresh && IsInstalledEnum(EnumType) && !IsInstalledEnum(SelectedEnumType))
{
m_PendingInstalledViewRefresh = FALSE;
bReload = TRUE; // Reload because we are switching from Available to Installed after something installed
}
BOOL TryRestoreSelection = SelectedEnumType == EnumType; BOOL TryRestoreSelection = SelectedEnumType == EnumType;
if (SelectedEnumType != EnumType) if (SelectedEnumType != EnumType)
SelectedEnumType = EnumType; SelectedEnumType = EnumType;
@ -812,16 +842,7 @@ CMainWindow::ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam)
BOOL BOOL
CMainWindow::InstallApplication(CAppInfo *Info) CMainWindow::InstallApplication(CAppInfo *Info)
{ {
if (Info) return Info && DownloadApplication(Info);
{
if (DownloadApplication(Info))
{
//FIXME: Delay UpdateApplicationsList(SelectedEnumType); until install completes
return TRUE;
}
}
return FALSE;
} }
BOOL BOOL

View file

@ -41,6 +41,7 @@ enum AppsCategories
ENUM_CAT_THEMES, ENUM_CAT_THEMES,
ENUM_CAT_OTHER, ENUM_CAT_OTHER,
ENUM_CAT_SELECTED, ENUM_CAT_SELECTED,
ENUM_LASTCATEGORY = ENUM_CAT_SELECTED - 1,
ENUM_ALL_INSTALLED = 30, ENUM_ALL_INSTALLED = 30,
ENUM_INSTALLED_APPLICATIONS, ENUM_INSTALLED_APPLICATIONS,
ENUM_UPDATES, ENUM_UPDATES,
@ -54,6 +55,12 @@ enum AppsCategories
inline BOOL inline BOOL
IsAvailableEnum(INT x) IsAvailableEnum(INT x)
{ {
C_ASSERT(ENUM_CAT_AUDIO == 1 && ENUM_CAT_THEMES == 15 && ENUM_CAT_OTHER == 16);
C_ASSERT(ENUM_LASTCATEGORY >= ENUM_CAT_OTHER);
C_ASSERT(ENUM_LASTCATEGORY < ENUM_CAT_SELECTED);
C_ASSERT(ENUM_LASTCATEGORY < ENUM_INSTALLED_MIN);
C_ASSERT(ENUM_CAT_SELECTED < ENUM_INSTALLED_MIN);
return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX); return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX);
} }
@ -68,7 +75,9 @@ enum UninstallCommandFlags
UCF_NONE = 0x00, UCF_NONE = 0x00,
UCF_MODIFY = 0x01, UCF_MODIFY = 0x01,
UCF_SILENT = 0x02, UCF_SILENT = 0x02,
UCF_SAMEPROCESS = 0x04,
}; };
DEFINE_ENUM_FLAG_OPERATORS(UninstallCommandFlags);
enum InstallerType enum InstallerType
{ {

View file

@ -175,7 +175,7 @@ class CAppInfoDisplay : public CUiWindow<CWindowImpl<CAppInfoDisplay>>
Create(HWND hwndParent); Create(HWND hwndParent);
VOID VOID
ShowAppInfo(CAppInfo *Info); ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText = false);
void void
SetWelcomeText(bool bAppwiz); SetWelcomeText(bool bAppwiz);
VOID VOID
@ -388,6 +388,8 @@ class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>>
void void
SetRedraw(BOOL bRedraw); SetRedraw(BOOL bRedraw);
void void
RefreshAvailableItem(PCWSTR PackageName);
void
SetFocusOnSearchBar(); SetFocusOnSearchBar();
BOOL BOOL
SetDisplayAppType(APPLICATION_VIEW_TYPE AppType); SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
@ -415,6 +417,9 @@ class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>>
VOID VOID
RestoreListSelection(const RESTORELISTSELECTION &Restore); RestoreListSelection(const RESTORELISTSELECTION &Restore);
VOID
RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText = false);
// this function is called when a item of listview get focus. // this function is called when a item of listview get focus.
// CallbackParam is the param passed to listview when adding the item (the one getting focus now). // CallbackParam is the param passed to listview when adding the item (the one getting focus now).
VOID VOID

View file

@ -65,6 +65,9 @@ class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
AppsCategories SelectedEnumType; AppsCategories SelectedEnumType;
public: public:
static HWND m_hLastFocus;
static bool m_PendingInstalledViewRefresh;
explicit CMainWindow(CAppDB *db, BOOL bAppwiz = FALSE); explicit CMainWindow(CAppDB *db, BOOL bAppwiz = FALSE);
~CMainWindow(); ~CMainWindow();

View file

@ -14,8 +14,10 @@
#include "configparser.h" #include "configparser.h"
extern LONG g_Busy; extern LONG g_Busy;
extern bool g_PendingInstalledViewRefresh;
#define WM_NOTIFY_OPERATIONCOMPLETED (WM_APP + 0) #define WM_NOTIFY_OPERATIONCOMPLETED (WM_APP + 0)
#define WM_NOTIFY_INSTALLERFINISHED (WM_APP + 1)
#define MAINWINDOWCLASSNAME L"ROSAPPMGR2" #define MAINWINDOWCLASSNAME L"ROSAPPMGR2"
#define MAINWINDOWMUTEX szWindowClass #define MAINWINDOWMUTEX szWindowClass

View file

@ -142,8 +142,7 @@ struct DownloadInfo
AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes); AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes);
szName = AppInfo.szDisplayName; szName = AppInfo.szDisplayName;
IType = AppInfo.GetInstallerType(); IType = AppInfo.GetInstallerType();
if (IType == INSTALLER_GENERATE) szPackageName = AppInfo.szIdentifier;
szPackageName = AppInfo.szIdentifier;
CConfigParser *cfg = static_cast<const CAvailableApplicationInfo&>(AppInfo).GetConfigParser(); CConfigParser *cfg = static_cast<const CAvailableApplicationInfo&>(AppInfo).GetConfigParser();
if (cfg) if (cfg)
@ -452,6 +451,8 @@ ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
return FALSE; return FALSE;
} }
if (hWndOwner && !IsWindowVisible(hWndOwner))
hWndOwner = NULL;
MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR); MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
return TRUE; return TRUE;
} }
@ -1090,8 +1091,12 @@ run:
SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_INSTALLING, 0); SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_INSTALLING, 0);
// TODO: issue an install operation separately so that the apps could be downloaded in the background // TODO: issue an install operation separately so that the apps could be downloaded in the background
WaitForSingleObject(shExInfo.hProcess, INFINITE); if (shExInfo.hProcess)
CloseHandle(shExInfo.hProcess); {
WaitForSingleObject(shExInfo.hProcess, INFINITE);
CloseHandle(shExInfo.hProcess);
SendMessageW(hMainWnd, WM_NOTIFY_INSTALLERFINISHED, 0, (LPARAM)(PCWSTR)Info.szPackageName);
}
} }
else else
{ {

View file

@ -160,6 +160,8 @@ StartProcess(const CStringW &Path, BOOL Wait)
{ {
EnableWindow(hMainWnd, TRUE); EnableWindow(hMainWnd, TRUE);
SetForegroundWindow(hMainWnd); SetForegroundWindow(hMainWnd);
// We got the real activation message during MsgWaitForMultipleObjects while
// we were disabled, we need to set the focus again now.
SetFocus(hMainWnd); SetFocus(hMainWnd);
} }

View file

@ -191,7 +191,7 @@ HandleUninstallCommand(CAppDB &db, UINT argcLeft, LPWSTR *argvLeft)
if (pInfo) if (pInfo)
{ {
retval = pInfo->UninstallApplication(silent ? UCF_SILENT : UCF_NONE); retval = pInfo->UninstallApplication((silent ? UCF_SILENT : UCF_NONE) | UCF_SAMEPROCESS);
} }
delete pDelete; delete pDelete;
return retval; return retval;
@ -368,7 +368,7 @@ ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
if (hWindow) if (hWindow)
{ {
/* Activate the window in the other instance */ /* Activate the window in the other instance */
ShowWindow(hWindow, SW_SHOW); ShowWindow(hWindow, SW_SHOWNA);
SwitchToThisWindow(hWindow, TRUE); SwitchToThisWindow(hWindow, TRUE);
if (bAppwizMode) if (bAppwizMode)
PostMessage(hWindow, WM_COMMAND, ID_ACTIVATE_APPWIZ, 0); PostMessage(hWindow, WM_COMMAND, ID_ACTIVATE_APPWIZ, 0);