diff --git a/go.mod b/go.mod index 8e577562..d3f1c870 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module cwtch.im/ui go 1.12 require ( - cwtch.im/cwtch v0.3.6 + cwtch.im/cwtch v0.3.7 git.openprivacy.ca/openprivacy/libricochet-go v1.0.8 github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect github.com/kr/pretty v0.1.0 // indirect diff --git a/go.sum b/go.sum index fd141d81..6c5bef65 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,14 @@ cwtch.im/cwtch v0.3.5 h1:L4hBYMRUSADodBz3gwIrYGXZf2V7HzTlzLUku9N3O9A= cwtch.im/cwtch v0.3.5/go.mod h1:I95rbE3aK8uic7LsMOB1lfJDSzlNsRUP0/5cFCLkD0Y= cwtch.im/cwtch v0.3.6 h1:a+BhoTpdlH5yI335HQDB7EEWZJqvNdoZnnjYLYne52Y= cwtch.im/cwtch v0.3.6/go.mod h1:NU6Pm4RgHm97b03U83W7/NabmRvBxHQMxM8/kZnH12Y= +cwtch.im/cwtch v0.3.7 h1:kcNQqxQLT03DKbkyXJGMmoROLcIGlsjw8++gNVq2Dxg= +cwtch.im/cwtch v0.3.7/go.mod h1:wbhUXmJohgHOLx0pPx96LqsDK89PL6Ai+ABL8YC9ZC4= cwtch.im/tapir v0.1.10 h1:V+TkmwXNd6gySZqlVw468wMYEkmDwMSyvhkkpOfUw7w= cwtch.im/tapir v0.1.10/go.mod h1:EuRYdVrwijeaGBQ4OijDDRHf7R2MDSypqHkSl5DxI34= cwtch.im/tapir v0.1.11 h1:JLm1MIYq4VXKzhj68+P8OuVPllAU9U6G0DtUor2fbc4= cwtch.im/tapir v0.1.11/go.mod h1:EuRYdVrwijeaGBQ4OijDDRHf7R2MDSypqHkSl5DxI34= +cwtch.im/tapir v0.1.13 h1:gGAtFyRnxLrs1SQRAeVXiO5MG2DUUTE621aTQQEJN7U= +cwtch.im/tapir v0.1.13/go.mod h1:1fu4d+cMCepVaMm5vHrp4N/romdjKR+R6P8cvdRXYtQ= git.openprivacy.ca/openprivacy/libricochet-go v1.0.4/go.mod h1:yMSG1gBaP4f1U+RMZXN85d29D39OK5s8aTpyVRoH5FY= git.openprivacy.ca/openprivacy/libricochet-go v1.0.6 h1:5o4K2qn3otEE1InC5v5CzU0yL7Wl7DhVp4s8H3K6mXY= git.openprivacy.ca/openprivacy/libricochet-go v1.0.6/go.mod h1:yMSG1gBaP4f1U+RMZXN85d29D39OK5s8aTpyVRoH5FY= @@ -42,6 +46,10 @@ github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORR github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20190601041439-ed7b1b5ee0f8/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.1 h1:A+VVUhf73TS5HRfCnfMBqTBujkbwY3Fo8sRSFvL3cIg= +github.com/gtank/ristretto255 v0.1.1/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -53,6 +61,8 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -78,6 +88,8 @@ github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20191101232336 github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20191101232336-18864661ae4f/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc= github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20191002095216-73192f6811d0 h1:SC92QLlGwzwrT3Xi5YzKvtVXFIriPP0Ui1AOIZgDyh8= github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20191002095216-73192f6811d0/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4= +go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= diff --git a/go/constants/attributes.go b/go/constants/attributes.go index 0868de16..7471c265 100644 --- a/go/constants/attributes.go +++ b/go/constants/attributes.go @@ -4,3 +4,6 @@ const Nick = "nick" const LastRead = "last-read" const Picture = "picture" const DefaultPassword = "default-password" + +const ProfileTypeV1DefaultPassword = "v1-defaultPassword" +const ProfileTypeV1Password = "v1-userPassword" diff --git a/go/handlers/appHandler.go b/go/handlers/appHandler.go index f58a137a..a2085a21 100644 --- a/go/handlers/appHandler.go +++ b/go/handlers/appHandler.go @@ -1,6 +1,7 @@ package handlers import ( + "cwtch.im/cwtch/app" "cwtch.im/cwtch/app/plugins" "cwtch.im/cwtch/event" "cwtch.im/ui/go/constants" @@ -12,7 +13,7 @@ import ( "time" ) -func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingFirst bool) { +func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingAccounts bool) { q := event.NewQueue() the.AppBus.Subscribe(event.NewPeer, q) the.AppBus.Subscribe(event.PeerError, q) @@ -21,7 +22,6 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingFirst bo the.AppBus.Subscribe(event.NetworkStatus, q) the.AppBus.Subscribe(event.ReloadDone, q) subscribed <- true - loadingV1Accounts := !reloadingFirst networkOffline := false timeSinceLastSuccess := time.Unix(0, 0) @@ -77,35 +77,24 @@ func App(gcd *ui.GrandCentralDispatcher, subscribed chan bool, reloadingFirst bo case event.AppError: if e.Data[event.Error] == event.AppErrLoaded0 { - - if loadingV1Accounts { - loadingV1Accounts = false - // TODO: only an error if other profiles are not loaded - if len(the.CwtchApp.ListPeers()) == 0 { - log.Infoln("couldn't load your config file. attempting to create one now") - if gcd.Version() == "development" { - the.CwtchApp.CreatePeer("tester", the.AppPassword) - } else { - the.CwtchApp.CreatePeer("alice", the.AppPassword) - } - } + if reloadingAccounts { + reloadingAccounts = false } else { gcd.ErrorLoaded0() } } case event.ReloadDone: - if the.Peer == nil { - loadingV1Accounts = true + reloadingAccounts = false + if len(the.CwtchApp.ListPeers()) == 0 { the.CwtchApp.LoadProfiles(the.AppPassword) } case event.NewPeer: onion := e.Data[event.Identity] peer := the.CwtchApp.GetPeer(onion) - if loadingV1Accounts { - the.CwtchApp.GetPeer(onion).SetAttribute(constants.DefaultPassword, "true") - loadingV1Accounts = false + if tag, exists := peer.GetAttribute(app.AttributeTag); !exists || tag == "" { + peer.SetAttribute(app.AttributeTag, constants.ProfileTypeV1DefaultPassword) } log.Infof("NewPeer for %v\n", onion) diff --git a/go/handlers/peerHandler.go b/go/handlers/peerHandler.go index cefe3d23..e64e6005 100644 --- a/go/handlers/peerHandler.go +++ b/go/handlers/peerHandler.go @@ -1,8 +1,10 @@ package handlers import ( + "cwtch.im/cwtch/app" "cwtch.im/cwtch/event" "cwtch.im/cwtch/protocol/connections" + "cwtch.im/ui/go/constants" "cwtch.im/ui/go/the" "cwtch.im/ui/go/ui" "git.openprivacy.ca/openprivacy/libricochet-go/log" @@ -23,6 +25,8 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) { eventBus.Subscribe(event.PeerStateChange, q) eventBus.Subscribe(event.PeerCreated, q) eventBus.Subscribe(event.NetworkStatus, q) + eventBus.Subscribe(event.ChangePasswordSuccess, q) + eventBus.Subscribe(event.ChangePasswordError, q) subscribed <- true @@ -105,6 +109,16 @@ func PeerHandler(onion string, uiManager ui.Manager, subscribed chan bool) { log.Errorf("found group that is nil :/") } } + case event.DeletePeer: + log.Infof("PeerHandler got DeletePeer, SHUTTING down!\n") + uiManager.ReloadProfiles() + return + case event.ChangePasswordSuccess: + peer.SetAttribute(app.AttributeTag, constants.ProfileTypeV1Password) + uiManager.ChangePasswordResponse(false) + case event.ChangePasswordError: + uiManager.ChangePasswordResponse(true) } + } } diff --git a/go/ui/gcd.go b/go/ui/gcd.go index 8e441618..445e6e7d 100644 --- a/go/ui/gcd.go +++ b/go/ui/gcd.go @@ -1,6 +1,7 @@ package ui import ( + "cwtch.im/cwtch/app" "cwtch.im/cwtch/event" "cwtch.im/cwtch/protocol/connections" "cwtch.im/ui/go/constants" @@ -37,12 +38,12 @@ type GrandCentralDispatcher struct { _ string `property:"selectedConversation,auto"` // profile management stuff - _ func() `signal:"Loaded"` - _ func(handle, displayname, image string) `signal:"AddProfile"` - _ func() `signal:"ErrorLoaded0"` - _ func() `signal:"ResetProfile"` - _ func() `signal:"ResetProfileList"` - _ func(onion string) `signal:"deleteProfile"` + _ func() `signal:"Loaded"` + _ func(handle, displayname, image, tag string) `signal:"AddProfile"` + _ func() `signal:"ErrorLoaded0"` + _ func() `signal:"ResetProfile"` + _ func() `signal:"ResetProfileList"` + _ func(failed bool) `signal:"ChangePasswordResponse"` // contact list stuff _ func(handle, displayName, image, server string, badge, status int, blocked bool, loading bool, lastMsgTime int) `signal:"AddContact"` @@ -78,11 +79,13 @@ type GrandCentralDispatcher struct { _ func() `signal:"onActivate,auto"` _ func(locale string) `signal:"setLocale,auto"` // profile managemenet - _ func(onion, nick string) `signal:"updateNick,auto"` - _ func(handle string) `signal:"loadProfile,auto"` - _ func(nick, password string) `signal:"createProfile,auto"` - _ func(password string) `signal:"unlockProfiles,auto"` - _ func() `signal:"reloadProfileList,auto"` + _ func(onion, nick string) `signal:"updateNick,auto"` + _ func(handle string) `signal:"loadProfile,auto"` + _ func(nick string, defaultPass bool, password string) `signal:"createProfile,auto"` + _ func(password string) `signal:"unlockProfiles,auto"` + _ func() `signal:"reloadProfileList,auto"` + _ func(onion string) `signal:"deleteProfile,auto"` + _ func(onion, currentPassword, newPassword string, defaultPass bool) `signal:"changePassword,auto""` // operating a profile _ func(message string, mid string) `signal:"sendMessage,auto"` _ func(onion string) `signal:"blockPeer,auto"` @@ -619,8 +622,26 @@ func (this *GrandCentralDispatcher) loadProfile(onion string) { } } -func (this *GrandCentralDispatcher) createProfile(nick, password string) { - the.CwtchApp.CreatePeer(nick, password) +func (this *GrandCentralDispatcher) createProfile(nick string, defaultPass bool, password string) { + if defaultPass { + the.CwtchApp.CreateTaggedPeer(nick, the.AppPassword, constants.ProfileTypeV1DefaultPassword) + } else { + the.CwtchApp.CreateTaggedPeer(nick, password, constants.ProfileTypeV1Password) + } +} + +func (this *GrandCentralDispatcher) changePassword(onion, currentPassword, newPassword string, defaultPass bool) { + tag, _ := the.CwtchApp.GetPeer(onion).GetAttribute(app.AttributeTag) + + if tag == constants.ProfileTypeV1DefaultPassword { + currentPassword = the.AppPassword + } + + if defaultPass { + newPassword = the.AppPassword + } + + the.CwtchApp.ChangePeerPassword(onion, currentPassword, newPassword) } func (this *GrandCentralDispatcher) reloadProfileList() { @@ -632,5 +653,6 @@ func (this *GrandCentralDispatcher) reloadProfileList() { } func (this *GrandCentralDispatcher) deleteProfile(onion string) { - //the.CwtchApp. + log.Infof("deleteProfile %v\n", onion) + the.CwtchApp.DeletePeer(onion) } diff --git a/go/ui/manager.go b/go/ui/manager.go index a23493dd..89ebc9ba 100644 --- a/go/ui/manager.go +++ b/go/ui/manager.go @@ -1,6 +1,7 @@ package ui import ( + "cwtch.im/cwtch/app" "cwtch.im/cwtch/model" "cwtch.im/cwtch/protocol/connections" "cwtch.im/ui/go/constants" @@ -122,8 +123,10 @@ func AddProfile(gcd *GrandCentralDispatcher, handle string) { pic = RandomProfileImage(handle) peer.SetAttribute(constants.Picture, pic) } - log.Infof("AddProfile %v %v %v\n", handle, nick, pic) - gcd.AddProfile(handle, nick, pic) + + tag, _ := peer.GetAttribute(app.AttributeTag) + log.Infof("AddProfile %v %v %v %v\n", handle, nick, pic, tag) + gcd.AddProfile(handle, nick, pic, tag) } } @@ -143,9 +146,13 @@ type Manager interface { AddSendMessageError(peer string, signature string, err string) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) + ReloadProfiles() + UpdateContactDisplayName(handle string, name string) UpdateContactStatus(handle string, status int, loading bool) UpdateContactAttribute(handle, key, value string) + + ChangePasswordResponse(error bool) } // NewManager returns a new Manager interface for a profile to the gcd @@ -244,6 +251,10 @@ func (this *manager) AddMessage(handle string, from string, message string, from }) } +func (this *manager) ReloadProfiles() { + this.gcd.reloadProfileList() +} + // UpdateContactDisplayName updates a contact's display name in the contact list and conversations func (this *manager) UpdateContactDisplayName(handle string, name string) { this.gcd.DoIfProfile(this.profile, func() { @@ -264,3 +275,7 @@ func (this *manager) UpdateContactAttribute(handle, key, value string) { this.gcd.UpdateContactAttribute(handle, key, value) }) } + +func (this *manager) ChangePasswordResponse(error bool) { + this.gcd.ChangePasswordResponse(error) +} diff --git a/i18n/translation_de.ts b/i18n/translation_de.ts index 47ebb17e..eb2209f8 100644 --- a/i18n/translation_de.ts +++ b/i18n/translation_de.ts @@ -36,18 +36,18 @@ BulletinOverlay - + new-bulletin-label Neue Meldung - + post-new-bulletin-label Post a new Bulletin Post Neue Meldung veröffentlichen - + title-placeholder title place holder text Titel... @@ -276,83 +276,113 @@ ProfileAddEditPane - + add-profile-title - + edit-profile-title - + profile-name - Profile name + Display name - - + + default-profile-name default suggested profile name - + profile-onion-label - Profile Onion + Onion - + + radio-use-password + Password + + + + + radio-no-password + Unencrypted (No password) + + + + + no-password-warning + Not using a password on this account means that all data stored locally will not be encrypted + + + + + current-password-label + Current Password + + + + password1-label Password - + password2-label Reenter password - + create-profile-btn Create Profile || Save Profile - + save-profile-btn - + password-error-match Passwords do not match - + + password-change-error + Error changing password: Supplied password rejected + + + + delete-profile-btn Delete Profile - + delete-confirm-label Type DELETE to confirm - + delete-profile-confirm-btn Really Delete Profile - + delete-confirm-text DELETE @@ -367,13 +397,13 @@ - + error-0-profiles-loaded-for-password 0 profiles loaded with that password - + unlock Unlock @@ -424,7 +454,7 @@ StackToolbar - + view-group-membership-tooltip View Group Membership diff --git a/i18n/translation_en.qm b/i18n/translation_en.qm index f14e39c3..318e9551 100644 Binary files a/i18n/translation_en.qm and b/i18n/translation_en.qm differ diff --git a/i18n/translation_en.ts b/i18n/translation_en.ts index 575e96fb..19d7121d 100644 --- a/i18n/translation_en.ts +++ b/i18n/translation_en.ts @@ -36,18 +36,18 @@ BulletinOverlay - + new-bulletin-label New Bulletin - + post-new-bulletin-label Post a new Bulletin Post Post new bulletin - + title-placeholder title place holder text title... @@ -276,83 +276,113 @@ ProfileAddEditPane - + add-profile-title Add new profile - + edit-profile-title Edit Profile - + profile-name - Profile name + Display name Display name - - + + default-profile-name default suggested profile name Alice - + profile-onion-label - Profile Onion + Onion Onion - + + radio-use-password + Password + Password + + + + radio-no-password + Unencrypted (No password) + Unencrypted (No password) + + + + no-password-warning + Not using a password on this account means that all data stored locally will not be encrypted + Not using a password on this account means that all data stored locally will not be encrypted + + + + current-password-label + Current Password + Current Password + + + password1-label Password Password - + password2-label Reenter password - Password + Reenter password - + create-profile-btn Create Profile || Save Profile Create Profile - + save-profile-btn Save Profile - + password-error-match Passwords do not match Passwords do not match - + + password-change-error + Error changing password: Supplied password rejected + Error changing password: Supplied password rejected + + + delete-profile-btn Delete Profile Delete Profile - + delete-confirm-label Type DELETE to confirm Type DELETE to confirm - + delete-profile-confirm-btn Really Delete Profile Really Delete Profile - + delete-confirm-text DELETE DELETE @@ -367,13 +397,13 @@ Please enter password - + error-0-profiles-loaded-for-password 0 profiles loaded with that password 0 profiles loaded with that password - + unlock Unlock Unlock @@ -424,7 +454,7 @@ StackToolbar - + view-group-membership-tooltip View Group Membership View Group Membership diff --git a/i18n/translation_fr.ts b/i18n/translation_fr.ts index 157be8fa..62b0b932 100644 --- a/i18n/translation_fr.ts +++ b/i18n/translation_fr.ts @@ -36,18 +36,18 @@ BulletinOverlay - + new-bulletin-label Nouveau bulletin - + post-new-bulletin-label Post a new Bulletin Post Envoyer un nouveau bulletin - + title-placeholder title place holder text titre... @@ -276,83 +276,113 @@ ProfileAddEditPane - + add-profile-title - + edit-profile-title - + profile-name - Profile name + Display name - - + + default-profile-name default suggested profile name - + profile-onion-label - Profile Onion + Onion - + + radio-use-password + Password + + + + + radio-no-password + Unencrypted (No password) + + + + + no-password-warning + Not using a password on this account means that all data stored locally will not be encrypted + + + + + current-password-label + Current Password + + + + password1-label Password - + password2-label Reenter password - + create-profile-btn Create Profile || Save Profile - + save-profile-btn - + password-error-match Passwords do not match - + + password-change-error + Error changing password: Supplied password rejected + + + + delete-profile-btn Delete Profile - + delete-confirm-label Type DELETE to confirm - + delete-profile-confirm-btn Really Delete Profile - + delete-confirm-text DELETE @@ -367,13 +397,13 @@ - + error-0-profiles-loaded-for-password 0 profiles loaded with that password - + unlock Unlock @@ -424,7 +454,7 @@ StackToolbar - + view-group-membership-tooltip View Group Membership diff --git a/i18n/translation_pt.ts b/i18n/translation_pt.ts index f7ab7e7a..f12bea3e 100644 --- a/i18n/translation_pt.ts +++ b/i18n/translation_pt.ts @@ -36,18 +36,18 @@ BulletinOverlay - + new-bulletin-label Novo Boletim - + post-new-bulletin-label Post a new Bulletin Post Postar novo boletim - + title-placeholder title place holder text título… @@ -276,83 +276,113 @@ ProfileAddEditPane - + add-profile-title - + edit-profile-title - + profile-name - Profile name + Display name - - + + default-profile-name default suggested profile name - + profile-onion-label - Profile Onion + Onion - + + radio-use-password + Password + + + + + radio-no-password + Unencrypted (No password) + + + + + no-password-warning + Not using a password on this account means that all data stored locally will not be encrypted + + + + + current-password-label + Current Password + + + + password1-label Password - + password2-label Reenter password - + create-profile-btn Create Profile || Save Profile - + save-profile-btn - + password-error-match Passwords do not match - + + password-change-error + Error changing password: Supplied password rejected + + + + delete-profile-btn Delete Profile - + delete-confirm-label Type DELETE to confirm - + delete-profile-confirm-btn Really Delete Profile - + delete-confirm-text DELETE @@ -367,13 +397,13 @@ - + error-0-profiles-loaded-for-password 0 profiles loaded with that password - + unlock Unlock @@ -424,7 +454,7 @@ StackToolbar - + view-group-membership-tooltip View Group Membership diff --git a/qml.qrc b/qml.qrc index f7d266c6..6713ce4b 100644 --- a/qml.qrc +++ b/qml.qrc @@ -29,9 +29,7 @@ qml/widgets/ScalingLabel.qml qml/widgets/SimpleButton.qml qml/widgets/StackToolbar.qml - qml/widgets/controls/Button.qml qml/widgets/controls/Loader.qml - qml/widgets/controls/Text.qml qml/widgets/controls/Variables.qml i18n/translation_de.qm i18n/translation_en.qm diff --git a/qml/overlays/BulletinOverlay.qml b/qml/overlays/BulletinOverlay.qml index 71e32c8d..47a4a64a 100644 --- a/qml/overlays/BulletinOverlay.qml +++ b/qml/overlays/BulletinOverlay.qml @@ -6,8 +6,7 @@ import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import "../widgets" -import "../widgets/controls" as Awesome +import "../widgets" as Widgets import "../fonts/Twemoji.js" as T import "../utils.js" as Utils import "../styles" @@ -176,7 +175,7 @@ ColumnLayout { width: parent.width - 50 } - SimpleButton { + Widgets.SimpleButton { id: replybtn visible: selected text: "reply" @@ -231,7 +230,7 @@ ColumnLayout { } - SimpleButton { // SEND MESSAGE BUTTON + Widgets.SimpleButton { // SEND MESSAGE BUTTON id: btnSend icon: "regular/paper-plane" text: "post" diff --git a/qml/overlays/ListOverlay.qml b/qml/overlays/ListOverlay.qml index 40c8acb8..3bfeebbd 100644 --- a/qml/overlays/ListOverlay.qml +++ b/qml/overlays/ListOverlay.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Material 2.0 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 -import "../widgets" +import "../widgets" as Widgets import "../widgets/controls" as Awesome import "../fonts/Twemoji.js" as T import "../utils.js" as Utils @@ -204,7 +204,7 @@ ColumnLayout { style: CwtchTextFieldStyle{} } - SimpleButton { // SEND MESSAGE BUTTON + Widgets.SimpleButton { // SEND MESSAGE BUTTON id: btnSend icon: "regular/paper-plane" text: "add" diff --git a/qml/panes/AddGroupPane.qml b/qml/panes/AddGroupPane.qml index 048e8aaa..4a0e45de 100644 --- a/qml/panes/AddGroupPane.qml +++ b/qml/panes/AddGroupPane.qml @@ -6,7 +6,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Window 2.11 import QtQuick.Controls 1.4 -import "../widgets" +import "../widgets" as Widgets import "../styles" ColumnLayout { // settingsPane @@ -14,7 +14,7 @@ ColumnLayout { // settingsPane anchors.fill: parent - StackToolbar { + Widgets.StackToolbar { id: stb text: qsTr("create-group-title") aux.visible: false @@ -37,7 +37,7 @@ ColumnLayout { // settingsPane spacing: 5 width: root.width - ScalingLabel { + Widgets.ScalingLabel { //: Server label text: qsTr("server-label") + ":" } @@ -48,7 +48,7 @@ ColumnLayout { // settingsPane text: "2c3kmoobnyghj2zw6pwv7d57yzld753auo3ugauezzpvfak3ahc4bdyd" } - ScalingLabel{ + Widgets.ScalingLabel{ //: Group name label text: qsTr("group-name-label") + ":" } @@ -60,7 +60,7 @@ ColumnLayout { // settingsPane text: qsTr("default-group-name") } - SimpleButton { + Widgets.SimpleButton { //: create group button text: qsTr("create-group-btn") diff --git a/qml/panes/GroupSettingsPane.qml b/qml/panes/GroupSettingsPane.qml index 7616158d..bb0499af 100644 --- a/qml/panes/GroupSettingsPane.qml +++ b/qml/panes/GroupSettingsPane.qml @@ -6,7 +6,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Window 2.11 import QtQuick.Controls 1.4 -import "../widgets" +import "../widgets" as Widgets import "../styles" import "../utils.js" as Utils @@ -16,7 +16,7 @@ ColumnLayout { // groupSettingsPane property string groupID property variant addrbook - StackToolbar { + Widgets.StackToolbar { id: toolbar aux.visible: false back.onClicked: theStack.pane = theStack.messagePane @@ -38,7 +38,7 @@ ColumnLayout { // groupSettingsPane leftPadding: 10 spacing: 5 - ScalingLabel { + Widgets.ScalingLabel { text: qsTr("server-label") + ":" } @@ -48,7 +48,7 @@ ColumnLayout { // groupSettingsPane readOnly: true } - SimpleButton { + Widgets.SimpleButton { icon: "regular/clipboard" text: qsTr("copy-btn") @@ -59,7 +59,7 @@ ColumnLayout { // groupSettingsPane } } - ScalingLabel { + Widgets.ScalingLabel { text: qsTr("invitation-label") + ":" } @@ -69,7 +69,7 @@ ColumnLayout { // groupSettingsPane readOnly: true } - SimpleButton { + Widgets.SimpleButton { icon: "regular/clipboard" text: qsTr("copy-btn") @@ -80,7 +80,7 @@ ColumnLayout { // groupSettingsPane } } - ScalingLabel{ + Widgets.ScalingLabel{ text: qsTr("group-name-label") + ":" } @@ -89,7 +89,7 @@ ColumnLayout { // groupSettingsPane style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } } - SimpleButton { + Widgets.SimpleButton { text: qsTr("save-btn") onClicked: { @@ -100,7 +100,7 @@ ColumnLayout { // groupSettingsPane } //: Invite someone to the group - ScalingLabel { text: qsTr("invite-to-group-label") } + Widgets.ScalingLabel { text: qsTr("invite-to-group-label") } ComboBox { id: cbInvite @@ -110,7 +110,7 @@ ColumnLayout { // groupSettingsPane style: CwtchComboBoxStyle{} } - SimpleButton { + Widgets.SimpleButton { text: qsTr("invite-btn") onClicked: { @@ -118,7 +118,7 @@ ColumnLayout { // groupSettingsPane } } - SimpleButton { + Widgets.SimpleButton { icon: "regular/trash-alt" text: qsTr("delete-btn") diff --git a/qml/panes/PeerSettingsPane.qml b/qml/panes/PeerSettingsPane.qml index a48b8f02..3b7927e5 100644 --- a/qml/panes/PeerSettingsPane.qml +++ b/qml/panes/PeerSettingsPane.qml @@ -6,7 +6,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Window 2.11 import QtQuick.Controls 1.4 -import "../widgets" +import "../widgets" as Widgets import "../styles" ColumnLayout { // peerSettingsPane @@ -14,7 +14,7 @@ ColumnLayout { // peerSettingsPane anchors.fill: parent property bool blocked - StackToolbar { + Widgets.StackToolbar { id: toolbar aux.visible: false @@ -38,7 +38,7 @@ ColumnLayout { // peerSettingsPane leftPadding: 10 spacing: 5 - ScalingLabel { + Widgets.ScalingLabel { text: qsTr("address-label") } @@ -48,7 +48,7 @@ ColumnLayout { // peerSettingsPane readOnly: true } - SimpleButton { + Widgets.SimpleButton { icon: "regular/clipboard" text: qsTr("copy-btn") @@ -60,7 +60,7 @@ ColumnLayout { // peerSettingsPane } } - ScalingLabel{ + Widgets.ScalingLabel{ text: qsTr("display-name-label") } @@ -69,7 +69,7 @@ ColumnLayout { // peerSettingsPane style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } } - SimpleButton { + Widgets.SimpleButton { text: qsTr("save-btn") onClicked: { @@ -80,7 +80,7 @@ ColumnLayout { // peerSettingsPane } - SimpleButton { + Widgets.SimpleButton { icon: "solid/hand-paper" text: root.blocked ? qsTr("unblock-btn") : qsTr("block-btn") @@ -94,7 +94,7 @@ ColumnLayout { // peerSettingsPane } } - SimpleButton { + Widgets.SimpleButton { icon: "regular/trash-alt" text: qsTr("delete-btn") diff --git a/qml/panes/ProfileAddEditPane.qml b/qml/panes/ProfileAddEditPane.qml index 97e371ef..5285fc00 100644 --- a/qml/panes/ProfileAddEditPane.qml +++ b/qml/panes/ProfileAddEditPane.qml @@ -1,21 +1,25 @@ import QtGraphicalEffects 1.0 import QtQuick 2.7 -import QtQuick.Controls 2.4 +import QtQuick.Controls 2.13 import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.3 import QtQuick.Window 2.11 -import QtQuick.Controls 1.4 -import "../widgets" -import "../styles" + +import "../widgets" as Widgets +// import "../styles" ColumnLayout { // Add Profile Pane id: profileAddEditPane anchors.fill: parent property string mode // edit or add + property string onion + property string tag + property bool deleting + property bool changingPassword - StackToolbar { + Widgets.StackToolbar { id: stb text: mode == "add" ? qsTr("add-profile-title") : qsTr("edit-profile-title") aux.visible: false @@ -24,29 +28,37 @@ ColumnLayout { // Add Profile Pane } function reset() { + mode = "add" txtProfileName.text = qsTr("default-profile-name") + changingPassword = false txtPassword1.text = "" txtPassword2.text = "" - deleteReset() + deleting = false + deleteConfirmLabel.color = "black" + tag = "" + confirmDeleteTxt.text = "" + radioUsePassword.checked = true + passwordChangeErrorLabel.visible = false } - function load(onion, name, pass) { + function load(userOnion, name, userTag) { + reset() + + mode = "edit" + tag = userTag + onion = userOnion + txtPassword1.text = "" + txtPassword2.text = "" onionLabel.text = onion txtProfileName.text = name - txtPassword1.text = pass - txtPassword2.text = pass - deleteReset() + if (tag == "v1-defaultPassword" || tag == "v1-default-password") { + radioNoPassword.checked = true + } else { + radioUsePassword.checked = true + } } - function deleteReset() { - deleteConfirmLabel.visible = false - deleteConfirmLabel.visible = false - deleteConfirmLabel.color = "black" - confirmDeleteTxt.visible = false - confirmDeleteTxt.text = "" - confirmDeleteBtn.visible = false - } Flickable { anchors.top: stb.bottom @@ -64,78 +76,142 @@ ColumnLayout { // Add Profile Pane spacing: 5 width: profileAddEditPane.width - ScalingLabel { + Widgets.ScalingLabel { //: Onion text: qsTr("profile-onion-label") + ":" visible: mode == "edit" } - ScalingLabel { + Widgets.ScalingLabel { id: onionLabel visible: mode == "edit" } - ScalingLabel { + Widgets.ScalingLabel { //: Display name text: qsTr("profile-name") + ":" } - TextField { + Widgets.TextField { id: txtProfileName Layout.fillWidth: true - style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } + //style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } //: default suggested profile name text: qsTr("default-profile-name") + + } - ScalingLabel { + RowLayout { + //id: radioButtons + + Widgets.RadioButton { + id: radioUsePassword + checked: true + //: Password + text: qsTr("radio-use-password") + visible: mode == "add" || tag == "v1-defaultPassword" + onClicked: { + changingPassword = true + } + } + + Widgets.RadioButton { + id: radioNoPassword + //: Unencrypted (No password) + text: qsTr("radio-no-password") + visible: mode == "add" || tag == "v1-defaultPassword" + onClicked: { + changingPassword = true + } + } + } + + Widgets.ScalingLabel { + id: noPasswordLabel + //: Not using a password on this account means that all data stored locally will not be encrypted + text: qsTr("no-password-warning") + visible: radioNoPassword.checked + } + + Widgets.ScalingLabel { + id: currentPasswordLabel + //: Current Password + text: qsTr("current-password-label") + ":" + visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword" + } + + Widgets.TextField { + id: txtCurrentPassword + Layout.fillWidth: true + echoMode: TextInput.Password + visible: radioUsePassword.checked && mode == "edit" && tag != "v1-defaultPassword" + } + + Widgets.ScalingLabel { + id: passwordLabel //: Password text: qsTr("password1-label") + ":" + visible: radioUsePassword.checked } - TextField { + Widgets.TextField { id: txtPassword1 Layout.fillWidth: true - style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } + //style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } echoMode: TextInput.Password - readOnly: mode == "edit" + visible: radioUsePassword.checked + + onTextEdited: { + changingPassword = true + } } - ScalingLabel { + Widgets.ScalingLabel { + id: passwordReLabel //: Reenter password text: qsTr("password2-label") + ":" + visible: radioUsePassword.checked } - TextField { + Widgets.TextField { id: txtPassword2 Layout.fillWidth: true - style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } + //style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } echoMode: TextInput.Password - readOnly: mode == "edit" - + visible: radioUsePassword.checked } - SimpleButton { + Widgets.SimpleButton { // ADD or SAVE button //: Create Profile || Save Profile text: mode == "add" ? qsTr("create-profile-btn") : qsTr("save-profile-btn") onClicked: { - if (txtPassword1.text != txtPassword2.text) { - passwordErrorLabel.visible = true + if (mode == "add") { + if (txtPassword1.text != txtPassword2.text) { + passwordErrorLabel.visible = true + } else { + gcd.createProfile(txtProfileName.text, radioNoPassword.checked, txtPassword1.text) + } } else { - if (mode == "add") { - gcd.createProfile(txtProfileName.text, txtPassword1.text) - } else { - gcd.updateNick(onionLabel.text, txtProfileName.text) - } - gcd.reloadProfileList() - parentStack.pane = parentStack.managementPane - } - } - } + gcd.updateNick(onion, txtProfileName.text) - ScalingLabel { + if (changingPassword) { + if (txtPassword1.text != txtPassword2.text) { + passwordErrorLabel.visible = true + } else { + gcd.changePassword(onion, txtCurrentPassword.text, txtPassword1.text, radioNoPassword.checked) + return + } + } + } + gcd.reloadProfileList() + parentStack.pane = parentStack.managementPane + } + } + + Widgets.ScalingLabel { id: passwordErrorLabel //: Passwords do not match text: qsTr("password-error-match") @@ -143,7 +219,17 @@ ColumnLayout { // Add Profile Pane color: "red" } - SimpleButton { + Widgets.ScalingLabel { + id: passwordChangeErrorLabel + //: Error changing password: Supplied password rejected + text: qsTr("password-change-error") + visible: false + color: "red" + } + + // ***** Delete button and confirm flow ***** + + Widgets.SimpleButton { //: Delete Profile text: qsTr("delete-profile-btn") icon: "regular/trash-alt" @@ -151,40 +237,38 @@ ColumnLayout { // Add Profile Pane onClicked: { - deleteConfirmLabel.visible = true - deleteConfirmLabel.visible = true - confirmDeleteTxt.visible = true - confirmDeleteBtn.visible = true + deleting = true } } - ScalingLabel { + Widgets.ScalingLabel { id: deleteConfirmLabel //: Type DELETE to confirm text: qsTr("delete-confirm-label")+ ":" - visible: false + visible: deleting } - TextField { + Widgets.TextField { id: confirmDeleteTxt Layout.fillWidth: true - style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } - visible: false + //style: CwtchTextFieldStyle{ width: tehcol.width * 0.8 } + visible: deleting } - SimpleButton { + Widgets.SimpleButton { id: confirmDeleteBtn icon: "regular/trash-alt" //: Really Delete Profile text: qsTr("delete-profile-confirm-btn") color: "red" - visible: false + visible: deleting onClicked: { //: DELETE if (confirmDeleteTxt.text == qsTr("delete-confirm-text")) { - gcd.deleteProfile(onionLabel.text) + deleteConfirmLabel.color = "black" + gcd.deleteProfile(onion) gcd.reloadProfileList() parentStack.pane = parentStack.managementPane } else { @@ -197,4 +281,17 @@ ColumnLayout { // Add Profile Pane }//end of column with padding }//end of flickable + + Connections { // UPDATE UNREAD MESSAGES COUNTER + target: gcd + + onChangePasswordResponse: function(error) { + if (!error) { + gcd.reloadProfileList() + parentStack.pane = parentStack.managementPane + } else { + passwordChangeErrorLabel.visible = true + } + } + } } \ No newline at end of file diff --git a/qml/panes/ProfileManagerPane.qml b/qml/panes/ProfileManagerPane.qml index cd0e1d0c..c288b4a4 100644 --- a/qml/panes/ProfileManagerPane.qml +++ b/qml/panes/ProfileManagerPane.qml @@ -8,7 +8,7 @@ import QtQuick.Window 2.11 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 -import "../widgets" +import "../widgets" as Widgets import "../widgets/controls" import "../styles" @@ -19,7 +19,7 @@ ColumnLayout { //leftPadding: 10 //spacing: 5 - ScalingLabel { + Widgets.ScalingLabel { anchors.horizontalCenter: parent.horizontalCenter wrapMode: TextEdit.Wrap //: Please enter password: @@ -31,9 +31,10 @@ ColumnLayout { anchors.horizontalCenter: parent.horizontalCenter style: CwtchTextFieldStyle{ width: thecol.width * 0.8 } echoMode: TextInput.Password + onAccepted: button.clicked() } - ScalingLabel { + Widgets.ScalingLabel { id: error anchors.horizontalCenter: parent.horizontalCenter color: "red" @@ -42,7 +43,7 @@ ColumnLayout { visible: false } - SimpleButton { + Widgets.SimpleButton { id: "button" anchors.horizontalCenter: parent.horizontalCenter @@ -75,7 +76,7 @@ ColumnLayout { Layout.minimumWidth: Layout.maximumWidth //Layout.maximumWidth: theStack.pane == theStack.emptyPane ? parent.width : 450 - ProfileList { + Widgets.ProfileList { anchors.fill: parent } } diff --git a/qml/widgets/ContactRow.qml b/qml/widgets/ContactRow.qml index 6e619d09..f74d838d 100644 --- a/qml/widgets/ContactRow.qml +++ b/qml/widgets/ContactRow.qml @@ -25,6 +25,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY property bool isHover property bool background: true property string type // profile or contact or button + property string tag // profile version/type // Profile property bool defaultPassword @@ -114,6 +115,22 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY // Profile + Image {// Profle Type + id: profiletype + + source: tag == "v1-userPassword" ? "qrc:/qml/images/fontawesome/solid/lock.svg" : "qrc:/qml/images/fontawesome/solid/lock-open.svg" + + anchors.right: parent.right + + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 1 * gcd.themeScale + anchors.rightMargin: (20 * gcd.themeScale) + parent.height + height: parent.height * 0.5 + width: height + + visible: type == "profile" + + } // Contact @@ -166,7 +183,6 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY gcd.loadProfile(handle) parentStack.pane = parentStack.profilePane } else if (type == "button") { // Add profile button - profileAddEditPane.mode = "add" profileAddEditPane.reset() parentStack.pane = parentStack.addEditProfilePane } @@ -197,8 +213,7 @@ Item { // LOTS OF NESTING TO DEAL WITH QT WEIRDNESS, SORRY onClicked: { - profileAddEditPane.mode = "edit" - profileAddEditPane.load(handle, displayName, "") + profileAddEditPane.load(handle, displayName, tag) parentStack.pane = parentStack.addEditProfilePane } } diff --git a/qml/widgets/ProfileList.qml b/qml/widgets/ProfileList.qml index f039416f..b7c1cc57 100644 --- a/qml/widgets/ProfileList.qml +++ b/qml/widgets/ProfileList.qml @@ -41,8 +41,9 @@ ColumnLayout { Connections { // ADD/REMOVE CONTACT ENTRIES target: gcd - onAddProfile: function(handle, displayName, image) { + onAddProfile: function(handle, displayName, image, tag) { + // don't add duplicates console.log("ProfileList onAddProfile for: " + handle) for (var i = 0; i < profilesModel.count; i++) { if (profilesModel.get(i)["_handle"] == handle) { @@ -50,12 +51,22 @@ ColumnLayout { } } - profilesModel.insert(profilesModel.count-1, + // find index for insert (sort by onion) + var index = profilesModel.count-1 + for (var i = 0; i < profilesModel.count-1; i++) { + if (profilesModel.get(i)["_handle"] > handle) { + index = i + break + } + } + + profilesModel.insert(index, { "_handle": handle, "_displayName": displayName, "_image": image, - "_type": "profile" + "_type": "profile", + "_tag": tag }) } @@ -77,6 +88,7 @@ ColumnLayout { _displayName: qsTr("add-new-profile-btn"), _image: "qrc:/qml/images/fontawesome/solid/user-plus.svg", _type: "button", + _tag: "," }) } } @@ -89,6 +101,7 @@ ColumnLayout { _displayName: qsTr("add-new-profile-btn") _image: "qrc:/qml/images/fontawesome/solid/user-plus.svg" _type: "button" + _tag: "" } } @@ -104,6 +117,7 @@ ColumnLayout { blocked: false loading: false type: _type + tag: _tag } } } diff --git a/qml/widgets/RadioButton.qml b/qml/widgets/RadioButton.qml new file mode 100644 index 00000000..187822e6 --- /dev/null +++ b/qml/widgets/RadioButton.qml @@ -0,0 +1,27 @@ +import QtQuick 2.7 + +import QtQuick.Controls 2.13 + + +RadioButton { + id: control + + property real size: 12 + spacing: 0 + + indicator: Rectangle { + width: 16 * gcd.themeScale + height: 16 * gcd.themeScale + anchors.verticalCenter: parent.verticalCenter + radius: 9 + border.width: 1 + + Rectangle { + anchors.fill: parent + visible: control.checked + color: "black" + radius: 9 + anchors.margins: 4 + } + } +} \ No newline at end of file diff --git a/qml/widgets/SimpleButton.qml b/qml/widgets/SimpleButton.qml index 2b3b67e8..25c6736d 100644 --- a/qml/widgets/SimpleButton.qml +++ b/qml/widgets/SimpleButton.qml @@ -4,7 +4,6 @@ import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.3 -import "controls" as Awesome import "../fonts/Twemoji.js" as T Rectangle { diff --git a/qml/widgets/StackToolbar.qml b/qml/widgets/StackToolbar.qml index 3b9f91e5..05ddc52e 100644 --- a/qml/widgets/StackToolbar.qml +++ b/qml/widgets/StackToolbar.qml @@ -4,7 +4,6 @@ import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.3 -import "controls" as Awesome import "../fonts/Twemoji.js" as T Rectangle { // OVERHEAD BAR ON STACK PANE diff --git a/qml/widgets/TextField.qml b/qml/widgets/TextField.qml new file mode 100644 index 00000000..6486f9d0 --- /dev/null +++ b/qml/widgets/TextField.qml @@ -0,0 +1,16 @@ +import QtQuick 2.7 + +import QtQuick.Controls 2.13 + + +TextField { + color: "black" + font.pointSize: 10 * gcd.themeScale + width: 100 + + background: Rectangle { + radius: 2 + color: windowItem.cwtch_background_color + border.color: windowItem.cwtch_color + } +} \ No newline at end of file diff --git a/qml/widgets/controls/Button.qml b/qml/widgets/controls/Button.qml deleted file mode 100644 index 1c120a50..00000000 --- a/qml/widgets/controls/Button.qml +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** -** Copyright (c) 2014 Ricardo do Valle Flores de Oliveira -** -** $BEGIN_LICENSE:MIT$ -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** -****************************************************************************/ - -import QtQuick 2.0 -import QtQuick.Controls 1.0 -import QtQuick.Controls.Styles 1.0 -import QtQuick.Layouts 1.0 - -Button { - id: button - property string icon - property color color: "black" - property font font - - style: ButtonStyle { - id: buttonstyle - property font font: button.font - property color foregroundColor: button.color - - background: Item { - Rectangle { - id: baserect - anchors.fill: parent - color: "transparent" - } - } - - label: Item { - implicitWidth: row.implicitWidth - implicitHeight: row.implicitHeight - - RowLayout { - id: row - anchors.centerIn: parent - spacing: 15 - - Text { - color: buttonstyle.foregroundColor - font.pointSize: buttonstyle.font.pointSize * 2 - font.family: awesome.family - renderType: Text.NativeRendering - text: awesome.loaded ? icon : "" - visible: !(icon === "") - } - Text { - color: buttonstyle.foregroundColor - font: buttonstyle.font - renderType: Text.NativeRendering - text: control.text - visible: !(control.text === "") - - Layout.alignment: Qt.AlignBottom - } - } - } - } -} diff --git a/qml/widgets/controls/Text.qml b/qml/widgets/controls/Text.qml deleted file mode 100644 index 8931eb17..00000000 --- a/qml/widgets/controls/Text.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** The MIT License (MIT) -** -** Copyright (c) 2014 Ricardo do Valle Flores de Oliveira -** -** $BEGIN_LICENSE:MIT$ -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** $END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtQuick.Controls 1.0 -import QtQuick.Layouts 1.0 - -Text { - id: root - - property alias spacing: row.spacing - property alias text: content.text - property color color: "black" - property font font - property string icon - - RowLayout { - id: row - - Text { - color: root.color - font.pointSize: root.font.pointSize - font.family: awesome.family - renderType: Text.NativeRendering - text: awesome.loaded ? icon : "" - } - - Text { - id: content - color: root.color - font.pointSize: root.font.pointSize - renderType: Text.NativeRendering - } - } -}