Save disabling of accounts, make persistent

If the user disables an account, this saves it so that on any
subsequent start-ups, the account won't be connected until the user
explicitly re-enables it.

ProtocolSettings were reworked to allow for publicly loading/saving
settings from BMessages, rather than solely from BViews.

In addition, all program-side disabling, enabling, and toggling of
accounts has been consolidated into ProtocolManager. This makes life
easier for other parts of the program that have to do these things
anyway.
This commit is contained in:
Jaidyn Ann 2021-08-16 11:58:27 -05:00
parent c492a46a65
commit c0580dfc17
8 changed files with 153 additions and 86 deletions

View File

@ -40,7 +40,10 @@ Account::Account(bigtime_t instanceId, ChatProtocol* cayap,
// Load settings file
BFile file(path.Path(), B_READ_ONLY);
if (fSettings->Unflatten(&file) == B_OK)
if (fSettings->GetBool("disabled", false) == false)
fStatus = fProtocol->UpdateSettings(fSettings);
else
fStatus = B_DONT_DO_THAT;
}
}

View File

@ -1,9 +1,11 @@
/*
* Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
* Jaidyn Levesque, jadedctrl@teknik.io
*/
#include <stdio.h>
@ -16,7 +18,9 @@
#include "Account.h"
#include "AppMessages.h"
#include "ChatProtocolMessages.h"
#include "ProtocolManager.h"
#include "ProtocolSettings.h"
#include "ChatProtocol.h"
#include "MainWindow.h"
#include "Server.h"
@ -126,25 +130,88 @@ void
ProtocolManager::AddAccount(ChatProtocolAddOn* addOn, const char* account,
BHandler* target)
{
TheApp* theApp = reinterpret_cast<TheApp*>(be_app);
// If already active, don't double-dip!
bool active = false;
_Server()->GetActiveAccounts().ValueFor(BString(account), &active);
if (active == true)
return;
bigtime_t instanceId = system_time();
ChatProtocol* cayap = addOn->Protocol();
Account* acc =
new Account(instanceId, cayap, account, addOn->Signature(), target);
// If account is disabled, just let it go
if (acc->InitCheck() == B_DONT_DO_THAT) {
delete acc;
return;
}
// Send a "whoops" notification if hits a failure
if (acc->InitCheck() != B_OK) {
else if (acc->InitCheck() != B_OK) {
BMessage error(APP_ACCOUNT_FAILED);
cayap->Icon()->Archive(&error);
error.AddString("name", account);
theApp->GetMainWindow()->MessageReceived(&error);
_MainWin()->MessageReceived(&error);
return;
}
fProtocolMap.AddItem(instanceId, cayap);
theApp->GetMainWindow()->GetServer()->AddProtocolLooper(
instanceId, cayap);
_Server()->AddProtocolLooper(instanceId, cayap);
}
void
ProtocolManager::EnableAccount(ProtocolSettings* settings, const char* account)
{
BMessage* msg = NULL;
if (settings->Load(account, &msg) == B_OK) {
if (msg->HasBool("disabled"))
msg->ReplaceBool("disabled", false);
else
msg->AddBool("disabled", false);
settings->Save(account, *msg);
}
AddAccount(settings->AddOn(), account, _MainWin());
}
void
ProtocolManager::DisableAccount(ProtocolSettings* settings, const char* account)
{
bool active = false;
int64 instance
= _Server()->GetActiveAccounts().ValueFor(BString(account), &active);
if (active == false)
return;
BMessage* msg = NULL;
if (settings->Load(account, &msg) == B_OK) {
if (msg->HasBool("disabled"))
msg->ReplaceBool("disabled", true);
else
msg->AddBool("disabled", true);
settings->Save(account, *msg);
}
BMessage remove(IM_MESSAGE);
remove.AddInt32("im_what", IM_PROTOCOL_DISABLE);
remove.AddInt64("instance", instance);
_MainWin()->PostMessage(&remove);
}
void
ProtocolManager::ToggleAccount(ProtocolSettings* settings, const char* account)
{
bool active = false;
int64 instance
= _Server()->GetActiveAccounts().ValueFor(BString(account), &active);
if (active == true)
DisableAccount(settings, account);
else
EnableAccount(settings, account);
}
@ -174,7 +241,7 @@ ProtocolManager::_LoadAccount(const char* imagePath, BEntry accountEntry,
if (id < 0)
return;
// If add-on's API version fits then load accounts...
// If add-on's API version fits then load accounts
ChatProtocolAddOn* addOn = new ChatProtocolAddOn(id, imagePath, protoIndex);
if (addOn->Version() != APP_VERSION)
return;
@ -198,3 +265,18 @@ ProtocolManager::_LoadAccount(ChatProtocolAddOn* addOn, BEntry accountEntry,
}
}
}
MainWindow*
ProtocolManager::_MainWin()
{
return ((TheApp*)be_app)->GetMainWindow();
}
Server*
ProtocolManager::_Server()
{
MainWindow* win = _MainWin();
return win ? win->GetServer() : NULL;
}

View File

@ -1,6 +1,7 @@
/*
* Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PROTOCOL_MANAGER_H
@ -18,6 +19,11 @@ class BBitmap;
class BDirectory;
class BHandler;
class MainWindow;
class ProtocolSettings;
class Server;
class ProtocolManager {
public:
bool Init(BDirectory dir, BHandler* target);
@ -33,8 +39,14 @@ public:
ChatProtocol* ProtocolInstance(bigtime_t identifier);
void AddAccount(ChatProtocolAddOn* addOn,
const char* account,
BHandler* target);
const char* account, BHandler* target);
void EnableAccount(ProtocolSettings* settings,
const char* account);
void DisableAccount(ProtocolSettings* settings,
const char* account);
void ToggleAccount(ProtocolSettings* settings,
const char* account);
private:
typedef KeyMap<BString, ChatProtocolAddOn*> AddOnMap;
@ -51,6 +63,9 @@ private:
void _LoadAccount(ChatProtocolAddOn* addOn,
BEntry accountEntry, BHandler* target);
MainWindow* _MainWin();
Server* _Server();
AddOnMap fAddOnMap;
ProtocolMap fProtocolMap;
};

View File

@ -76,7 +76,7 @@ ProtocolSettings::Load(const char* account, BView* parent)
BMessage* settings = NULL;
if (account) {
status_t ret = _Load(account, &settings);
status_t ret = Load(account, &settings);
if (ret != B_OK)
return ret;
}
@ -84,6 +84,30 @@ ProtocolSettings::Load(const char* account, BView* parent)
}
status_t
ProtocolSettings::Load(const char* account, BMessage** settings)
{
if (!account || !settings)
return B_BAD_VALUE;
status_t ret = B_ERROR;
// Find user's settings path
BPath path(AccountPath(fAddOn->Signature(), fAddOn->ProtoSignature()));
if ((ret = path.InitCheck()) != B_OK)
return ret;
// Load settings file
path.Append(account);
BFile file(path.Path(), B_READ_ONLY);
BMessage* msg = new BMessage();
ret = msg->Unflatten(&file);
*settings = msg;
return ret;
}
status_t
ProtocolSettings::Save(const char* account, BView* parent, BString* errorText)
{
@ -95,12 +119,17 @@ ProtocolSettings::Save(const char* account, BView* parent, BString* errorText)
if (status != B_OK)
return status;
return Save(account, settings);
}
status_t ret = B_ERROR;
status_t
ProtocolSettings::Save(const char* account, BMessage settings)
{
// Find user's settings path
BPath path(AccountPath(fAddOn->Signature(), fAddOn->ProtoSignature()));
status_t ret;
if ((ret = path.InitCheck()) != B_OK)
return ret;
@ -155,27 +184,3 @@ ProtocolSettings::Delete(const char* account)
}
status_t
ProtocolSettings::_Load(const char* account, BMessage** settings)
{
*settings = NULL;
if (!account || !settings)
return B_BAD_VALUE;
status_t ret = B_ERROR;
// Find user's settings path
BPath path(AccountPath(fAddOn->Signature(), fAddOn->ProtoSignature()));
if ((ret = path.InitCheck()) != B_OK)
return ret;
// Load settings file
path.Append(account);
BFile file(path.Path(), B_READ_ONLY);
BMessage* msg = new BMessage();
ret = msg->Unflatten(&file);
*settings = msg;
return ret;
}

View File

@ -25,15 +25,16 @@ public:
BObjectList<BString> Accounts() const;
status_t Load(const char* account, BView* parent);
status_t Load(const char* account, BMessage** settings);
status_t Save(const char* account, BView* parent,
BString* errorText = NULL);
status_t Save(const char* account, BMessage settings);
status_t Rename(const char* from, const char* to);
status_t Delete(const char* account);
private:
status_t _Load(const char* account, BMessage** settings);
ChatProtocolAddOn* fAddOn;
ProtocolTemplate fTemplate;
status_t fStatus;

View File

@ -195,12 +195,8 @@ AccountsWindow::MessageReceived(BMessage* msg)
break;
const char* account = item->Account();
int64 instance = _AccountInstance(account);
if (instance == -1)
_EnableAccount(account, item->Settings());
else
_DisableAccount(account, instance);
ProtocolManager::Get()->ToggleAccount(item->Settings(), account);
fListView->DeselectAll();
break;
}
case kAccountAdded:
@ -232,7 +228,7 @@ AccountsWindow::MessageReceived(BMessage* msg)
= new AccountListItem(settings, account.String());
fListView->AddItem(listItem);
_EnableAccount(account, settings);
ProtocolManager::Get()->EnableAccount(settings, account);
} else {
// Rename list item
for (int32 i = 0; i < fListView->CountItems(); i++) {
@ -274,28 +270,6 @@ AccountsWindow::_LoadListView(ProtocolSettings* settings)
}
void
AccountsWindow::_DisableAccount(const char* account, int64 instance)
{
BMessage* remove = new BMessage(IM_MESSAGE);
remove->AddInt32("im_what", IM_PROTOCOL_DISABLE);
remove->AddInt64("instance", instance);
((TheApp*)be_app)->GetMainWindow()->PostMessage(remove);
fToggleButton->SetLabel(B_TRANSLATE("Enable"));
fToggleButton->SetEnabled(false);
}
void
AccountsWindow::_EnableAccount(const char* account,
ProtocolSettings* settings)
{
ProtocolManager::Get()->AddAccount(settings->AddOn(), account,
((TheApp*)be_app)->GetMainWindow());
}
int64
AccountsWindow::_AccountInstance(const char* account)
{

View File

@ -30,10 +30,6 @@ private:
void _LoadListView(ProtocolSettings* settings);
void _DisableAccount(const char* account, int64 instance);
void _EnableAccount(const char* account,
ProtocolSettings* settings);
int64 _AccountInstance(const char* account);
};

View File

@ -139,23 +139,14 @@ MainWindow::MessageReceived(BMessage* message)
}
case APP_TOGGLE_ACCOUNT:
{
ProtocolManager* protoMan = ProtocolManager::Get();
ProtocolSettings* settings = NULL;
BString account = message->FindString("account");
int64 instance = message->GetInt64("instance", -1);
message->FindPointer("settings", (void**)&settings);
if (account.IsEmpty() == false && settings != NULL) {
// Enable
if (instance == -1)
ProtocolManager::Get()->AddAccount(settings->AddOn(),
account, this);
else {
BMessage remove(IM_MESSAGE);
remove.AddInt32("im_what", IM_PROTOCOL_DISABLE);
remove.AddInt64("instance", instance);
PostMessage(&remove);
}
}
if (account.IsEmpty() == false && settings != NULL)
protoMan->ToggleAccount(settings, account);
break;
}
case APP_NEW_CHAT: