Save state of root and profile panes open, and selected profile and
the build was successful Details

conversation; jump to those when reloading
This commit is contained in:
Dan Ballard 2020-12-02 18:15:36 -08:00
parent 3687ead49f
commit b920d3ab8b
10 changed files with 155 additions and 32 deletions

View File

@ -12,3 +12,7 @@ const ProfileTypeV1Password = "v1-userPassword"
// PeerOnline stores state on if the peer believes it is online
const PeerOnline = "peer-online"
const StateProfilePane = "state-profile-pane"
const StateSelectedConversation = "state-selected-conversation"
const StateSelectedProfileTime = "state-selected-profile-time"

View File

@ -25,7 +25,15 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
subscribed <- true
the.CwtchApp.QueryACNVersion()
gcd.Loaded()
initialProfileLoad := false
if !reloadingAccounts {
initialProfileLoad = true
the.CwtchApp.LoadProfiles(the.AppPassword)
}
var latestProfileSelectedTs int64 = 0
var latestProfileSelectedOnion = ""
for {
e := q.Next()
@ -61,6 +69,9 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
if e.Data[event.Error] == event.AppErrLoaded0 {
if reloadingAccounts {
reloadingAccounts = false
} else if initialProfileLoad {
initialProfileLoad = false
gcd.Loaded()
} else {
gcd.ErrorLoaded0()
}
@ -68,10 +79,28 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
case event.ReloadDone:
reloadingAccounts = false
// profilePane: 3 as per main.qml
if gcd.GlobalSettings.StateRootPane == 3 && latestProfileSelectedOnion != "" {
gcd.Broadcast("ResetMessagePane")
gcd.Broadcast("ResetProfile")
gcd.SetSelectedProfile(latestProfileSelectedOnion)
gcd.LoadProfile(latestProfileSelectedOnion)
gcd.ChangeRootPane(3)
}
gcd.Loaded()
if len(the.CwtchApp.ListPeers()) == 0 {
initialProfileLoad = true
the.CwtchApp.LoadProfiles(the.AppPassword)
}
case event.NewPeer:
if initialProfileLoad {
initialProfileLoad = false
gcd.Loaded()
}
onion := e.Data[event.Identity]
p := the.CwtchApp.GetPeer(onion)
@ -90,7 +119,7 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
the.CwtchApp.AddPeerPlugin(onion, plugins.NETWORKCHECK)
}
log.Infof("NewPeer for %v\n", onion)
log.Debugf("NewPeer for %v\n", onion)
ui.AddProfile(gcd, onion)
incSubscribed := make(chan bool)
@ -110,6 +139,17 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts
if exists && blockUnkownPeers == "true" {
the.EventBus.Publish(event.NewEvent(event.BlockUnknownPeers, map[event.Field]string{}))
}
if reloadingAccounts {
lastSelectedTime, ok := p.GetAttribute(attr.GetSettingsScope(constants.StateSelectedProfileTime))
if ok {
lastSelectedTs, _ := strconv.ParseInt(lastSelectedTime, 10, 64)
if lastSelectedTs > latestProfileSelectedTs {
latestProfileSelectedTs = lastSelectedTs
latestProfileSelectedOnion = onion
}
}
}
}
}

View File

@ -12,6 +12,7 @@ import (
"github.com/therecipe/qt/qml"
"strconv"
"sync"
"time"
"cwtch.im/ui/go/the"
"encoding/base32"
@ -35,8 +36,7 @@ type GrandCentralDispatcher struct {
profileLock sync.Mutex
conversationLock sync.Mutex
m_selectedProfile string
m_selectedConversation string
m_selectedProfile string
_ int `property:"torStatus"`
_ string `property:"os"`
@ -49,10 +49,13 @@ type GrandCentralDispatcher struct {
_ string `property:"buildDate"`
_ string `property:"assetPath"`
_ string `property:"selectedProfile,auto"`
_ string `property:"selectedConversation,auto"`
_ string `property:"selectedConversation,auto,changed"`
_ bool `property:"experimentsEnabled,auto,changed"`
_ map[string]bool `property:"experiments,auto,changed"`
// general ui
_ func(pant int) `signal:"ChangeRootPane"`
_ func(pane int) `signal:"ChangeProfilePane"`
// profile management stuff
_ func() `signal:"Loaded"`
_ func(handle, displayname, image, tag string, online bool) `signal:"AddProfile"`
@ -99,9 +102,11 @@ type GrandCentralDispatcher struct {
_ func(onion, nick string, authorization string, storage string) `signal:"SupplyPeerSettings"`
_ func(server string, key_types []string, keys []string) `signal:"SupplyServerSettings"`
// signals emitted from the ui (written in go, below)
// signals emitted from the ui (and implemented in go, below)
// ui
_ func() `signal:"onActivate,auto"`
_ func() `signal:"onActivate,auto"`
_ func(pane int) `signal:"setRootPaneState",auto`
_ func(pane int) `signal:"setProfilePaneState",auto`
// profile managemenet
_ func(onion, nick string) `signal:"updateNick,auto"`
_ func(handle string) `signal:"loadProfile,auto"`
@ -152,6 +157,15 @@ func (this *GrandCentralDispatcher) init() {
this.SetExperimentsEnabled(this.GlobalSettings.ExperimentsEnabled)
this.SetExperiments(this.GlobalSettings.Experiments)
this.AndroidCwtchActivity = android.NewCwtchActivity(nil)
// Per main.qml
// managementPane:0 settingsPane:1 addEditProfilePane:2 profilePane:3 addEditServerPane:4
// We can't support addEditProfile(2) or addEditServer(4) as we don't store the target id for those yet: TODO
// We don't switch here to profilePane(3) as we need to wait for appHandler to identify and set the selectedProfile
// managementPane(0) is a NOP as it's default pane
if this.GlobalSettings.StateRootPane == 1 {
this.ChangeRootPane(this.GlobalSettings.StateRootPane)
}
}
// GetUiManager gets (and creates if required) a ui Manager for the supplied profile id
@ -178,6 +192,11 @@ func (this *GrandCentralDispatcher) setSelectedProfile(onion string) {
this.profileLock.Lock()
defer this.profileLock.Unlock()
p := the.CwtchApp.GetPeer(onion)
if p != nil {
p.SetAttribute(attr.GetSettingsScope(constants.StateSelectedProfileTime), strconv.FormatInt(time.Now().Unix(), 10))
}
this.m_selectedProfile = onion
}
@ -185,6 +204,11 @@ func (this *GrandCentralDispatcher) selectedProfileChanged(onion string) {
this.SelectedProfileChanged(onion)
}
func (this *GrandCentralDispatcher) setRootPaneState(pane int) {
this.GlobalSettings.StateRootPane = pane
WriteGlobalSettings(this.GlobalSettings)
}
// DoIfProfile performs a gcd action for a profile IF it is the currently selected profile in the UI
// otherwise it does nothing. it also locks profile switching for the duration of the action
func (this *GrandCentralDispatcher) DoIfProfile(profile string, fn func()) {
@ -208,7 +232,14 @@ func (this *GrandCentralDispatcher) DoIfProfileElse(profile string, fn func(), e
}
}
func (this *GrandCentralDispatcher) selectedConversation() string {
func (this *GrandCentralDispatcher) setProfilePaneState(pane int) {
this.profileLock.Lock()
defer this.profileLock.Unlock()
the.Peer.SetAttribute(attr.GetSettingsScope(constants.StateProfilePane), strconv.Itoa(pane))
}
/*func (this *GrandCentralDispatcher) selectedConversation() string {
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
@ -219,11 +250,13 @@ func (this *GrandCentralDispatcher) setSelectedConversation(handle string) {
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
the.Peer.SetAttribute(attr.GetSettingsScope(constants.StateSelectedConversation), handle)
this.m_selectedConversation = handle
}
}*/
func (this *GrandCentralDispatcher) selectedConversationChanged(handle string) {
this.SelectedConversationChanged(handle)
the.Peer.SetAttribute(attr.GetSettingsScope(constants.StateSelectedConversation), handle)
}
// DoIfConversation performs a gcd action for a conversation IF it is the currently selected conversation in the UI
@ -232,7 +265,7 @@ func (this *GrandCentralDispatcher) DoIfConversation(conversation string, fn fun
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
if this.m_selectedConversation == conversation {
if this.SelectedConversation() == conversation {
fn()
}
}
@ -242,7 +275,7 @@ func (this *GrandCentralDispatcher) DoIfConversationElse(conversation string, fn
this.conversationLock.Lock()
defer this.conversationLock.Unlock()
if this.m_selectedConversation == conversation {
if this.SelectedConversation() == conversation {
fn()
} else {
elseFn()
@ -788,6 +821,33 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) {
}))
}
}
selectedPane, pok := the.Peer.GetAttribute(attr.GetSettingsScope(constants.StateProfilePane))
if pok {
selectedPaneId, err := strconv.Atoi(selectedPane)
if err == nil {
// emptyPane:0 addPeerGroupPane:4 main.qml
if selectedPaneId != 0 && selectedPaneId != 4 {
selectedContact, cok := the.Peer.GetAttribute(attr.GetSettingsScope(constants.StateSelectedConversation))
if cok {
this.Broadcast("ResetMessagePane")
this.SetSelectedConversation(selectedContact)
this.TimelineInterface.handle = selectedContact
this.loadMessagesPane(selectedContact)
if isPeer(selectedContact) {
this.requestPeerSettings(selectedContact)
} else {
this.requestGroupSettings(selectedContact)
}
this.ChangeProfilePane(selectedPaneId)
}
} else {
this.ChangeProfilePane(selectedPaneId)
}
}
}
}
func (this *GrandCentralDispatcher) createProfile(nick string, defaultPass bool, password string) {

View File

@ -190,7 +190,7 @@ func AddProfile(gcd *GrandCentralDispatcher, handle string) {
online, _ := p.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
log.Infof("AddProfile %v %v %v %v %v\n", handle, nick, picPath, tag, online)
log.Debugf("AddProfile %v %v %v %v %v\n", handle, nick, picPath, tag, online)
gcd.AddProfile(handle, nick, picPath, tag, online == event.True)
}
}

View File

@ -22,6 +22,7 @@ type GlobalSettings struct {
PreviousPid int64
ExperimentsEnabled bool
Experiments map[string]bool
StateRootPane int
}
var DefaultGlobalSettings = GlobalSettings{
@ -31,6 +32,7 @@ var DefaultGlobalSettings = GlobalSettings{
PreviousPid: -1,
ExperimentsEnabled: false,
Experiments: make(map[string]bool),
StateRootPane: 0,
}
func InitGlobalSettingsFile(directory string, password string) error {

17
main.go
View File

@ -69,7 +69,7 @@ func main() {
logfileDefault := "cwtch_log.txt"
flagDebug := flag.Bool("debug", false, "turn on extra logging. WARNING: THIS MAY EXPOSE PRIVATE INFORMATION IN CONSOLE OUTPUT!")
flagDebug := flag.Bool("debug", false, "turn on extra debug level logging. WARNING: THIS MAY EXPOSE PRIVATE INFORMATION IN CONSOLE OUTPUT!")
flagLogFile := flag.Bool("logfile", false, "instead of console output, log to $HOME/.cwtch/"+logfileDefault)
flagLocal := flag.Bool("local", false, "load user interface from the local folder \"qml\" instead of the built-in UI")
flagService := flag.Bool("service", false, "run this process as an android service")
@ -89,17 +89,14 @@ func main() {
log.SetLevel(log.LevelInfo)
}
// TESTING
if buildVer == "" {
log.SetLevel(log.LevelDebug)
}
log.ExcludeFromPattern("connection/connection")
//log.ExcludeFromPattern("outbound/3dhauthchannel")
log.ExcludeFromPattern("event/eventmanager")
log.ExcludeFromPattern("service.go")
log.ExcludeFromPattern("tor/BaseOnionService.go")
log.ExcludeFromPattern("applications/auth.go")
//log.ExcludeFromPattern("connections/engine.go")
log.ExcludeFromPattern("connections/engine.go")
log.ExcludeFromPattern("bridge/pipeBridge.go")
log.ExcludeFromPattern("app/appBridge.go")
log.Infoln("ui main()")
@ -225,10 +222,8 @@ func mainUi(flagLocal bool, flagClientUI bool) {
gcd.TimelineInterface = ui.NewMessageModel(nil)
engine.RootContext().SetContextProperty("mm", gcd.TimelineInterface)
engine.RootContext().SetContextProperty("androidCwtchActivity", gcd.AndroidCwtchActivity)
engine.Load(qmlSource)
go loadNetworkingAndFiles(gcd, false, flagClientUI)
@ -328,8 +323,4 @@ func loadNetworkingAndFiles(gcd *ui.GrandCentralDispatcher, service bool, client
go servers.LaunchServiceManager(gcd, the.ACN, path.Join(the.CwtchDir, "servers"))
<-subscribed
}
if !service && !clientUI {
the.CwtchApp.LoadProfiles(the.AppPassword)
}
}

View File

@ -108,7 +108,7 @@ ApplicationWindow {
onRightMenu: {
// If a group is selected....
if (gcd.selectedConversation.length == 32) {
if (Utils.isGroup(gcd.selectedConversation)) {
theStack.pane = theStack.groupProfilePane
gcd.requestGroupSettings(gcd.selectedConversation)
} else {
@ -255,6 +255,7 @@ ApplicationWindow {
ServerInfoPane { anchors.fill: parent }
onCurrentIndexChanged: {
gcd.setProfilePaneState(theStack.currentIndex)
parentStack.updateToolbar()
if (currentIndex == emptyPane) {
toolbar.hideTitle()
@ -284,6 +285,19 @@ ApplicationWindow {
}
}
Connections {
target: gcd
onChangeRootPane: function(pane) {
parentStack.currentIndex = pane
}
onChangeProfilePane: function(pane) {
theStack.currentIndex = pane
}
}
focus: true
Keys.onPressed: {
if (event.key == Qt.Key_Back) {
@ -292,7 +306,11 @@ ApplicationWindow {
}
}
onCurrentIndexChanged : { updateToolbar(); statusbar.resetHeight() }
onCurrentIndexChanged : {
gcd.setRootPaneState(parentStack.currentIndex)
updateToolbar();
statusbar.resetHeight()
}
function updateToolbar() {
if (rootStack.splash == true) {

View File

@ -224,5 +224,4 @@ Rectangle {
}
}

View File

@ -125,7 +125,7 @@ ColumnLayout {
"_authorization": authorization,
"_loading": loading,
"_loading": loading,
"_lastMsgTs": lastMsgTs
"_lastMsgTs": lastMsgTs,
}
model.insert(index, newContact)
@ -173,6 +173,7 @@ ColumnLayout {
rowColor: (_authorization == Const.auth_unknown) ? Theme.backgroundHilightElementColor : Theme.backgroundMainColor
Layout.fillWidth: true
visible: filterContact(displayName, handle)
isActive: gcd.selectedConversation == _handle
}
}

View File

@ -98,7 +98,6 @@ Opaque.PortraitRow {
onClicked: function() {
gcd.broadcast("ResetMessagePane")
isActive = true
theStack.pane = theStack.messagePane
mm.setHandle(handle)
gcd.loadMessagesPane(handle)
@ -149,10 +148,19 @@ Opaque.PortraitRow {
}
}
onIncContactUnreadCount: function(handle) {
onIncContactUnreadCount: function(_handle) {
if (handle == _handle && gcd.selectedConversation != handle) {
badge++
}
}
onSelectedConversationChanged: function() {
if (handle == gcd.selectedConversation) {
isActive = true
badge = 0
} else {
isActive = false
}
}
}
}