mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-09-14 19:32:10 +02:00
Compare commits
768 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68dca6e3d9 | |||
| 017f883e0b | |||
| 77b5c95f75 | |||
| 9d052c8339 | |||
| d67623a657 | |||
| c740b3dd46 | |||
| 2ef5f7f96f | |||
| 404568d795 | |||
| b5a6337a0c | |||
| 82170c3fbd | |||
| e6d6275fcc | |||
| 97c865a127 | |||
| 1ff21f0ee0 | |||
| 2a3dca4467 | |||
| d4ecfcceec | |||
| ec5d503e4d | |||
| 346391ca2d | |||
| 9074cdf340 | |||
| 2fcf3604a8 | |||
| 34e5185fa1 | |||
| e09e0e69ca | |||
| 963c98e588 | |||
| 92acb823a4 | |||
| b967b1288f | |||
| 1db271ce90 | |||
| 58c64025e3 | |||
| 643a7a87aa | |||
| 5e9ed5d713 | |||
| 78e492c764 | |||
| 59c2a3642b | |||
| 40ca923745 | |||
| 03af6cecaa | |||
| 3992e447f4 | |||
| 14a9edeb73 | |||
| 92f1e9f7ec | |||
| 19c294c53e | |||
| fe88ea5c05 | |||
| c9d551213a | |||
| 1e86a33ceb | |||
| 551dd229f5 | |||
| 5ecf3c4147 | |||
| 91bb2f4df0 | |||
| ae3a0ae83d | |||
| 63ce7523de | |||
| 9e3b92bfc1 | |||
| bc1767fb84 | |||
| f917096cc7 | |||
| 308926a2ae | |||
| 76f2b1a454 | |||
| d899e4b38b | |||
| e1422e35cc | |||
| 2c00c6bb81 | |||
| 7e56ba6408 | |||
| 8ceb70e67d | |||
| 37d5efef1d | |||
| 924065c26e | |||
| 58cc7ea10d | |||
| f93e275ddf | |||
| 06d2a5f715 | |||
| 3a7455eafe | |||
| 8b676fe6ce | |||
| 54d12686af | |||
| f231256402 | |||
| 410ead66f8 | |||
| c833a810af | |||
| 50f1336b1d | |||
| 60ed0b8cde | |||
| cc55a81c1b | |||
| f832e04e9e | |||
| fc760b9a0c | |||
| 9addff0521 | |||
| dcaa3aab19 | |||
| 628785c68c | |||
| a5aa396fda | |||
| f53a9f05e3 | |||
| 7749b14156 | |||
| c15f339718 | |||
| 775f590bfa | |||
| 76408ea56f | |||
| a391d8ee83 | |||
| 48c38f6e1d | |||
| 37c5fba162 | |||
| 23e99b1d44 | |||
| 8432240a47 | |||
| a4bab743d6 | |||
| 60766789ab | |||
| ca014f881c | |||
| 886eabe26c | |||
| 65b7167b5f | |||
| abbdde851e | |||
| 54ac54aba6 | |||
| 184340f400 | |||
| 93dd6813e8 | |||
| b689b08711 | |||
| 1479a097d6 | |||
| e4967ea46d | |||
| 3f28f18fb4 | |||
| 1b90e0f65e | |||
| 756ed649e6 | |||
| fbc423e2a7 | |||
| f04cdb6a13 | |||
| 63b58b1cfe | |||
| 77e656d8e4 | |||
| a673957bd0 | |||
| c99a0c9974 | |||
| 0fb06d0ff2 | |||
| c51eebfe22 | |||
| a51b34b48f | |||
| 1b239bada1 | |||
| 50ab1a6ac3 | |||
| f181f1fadc | |||
| c686349922 | |||
| 5f44a1f4ad | |||
| a968938832 | |||
| 8d67f3dfdc | |||
| 973ae8cb5d | |||
| a4747b0d7b | |||
| f07640cc84 | |||
| c235c55b19 | |||
| 485ef684be | |||
| 7caca22e57 | |||
| f1d9e32bf5 | |||
| 23d5fa3107 | |||
| 4e7d8aba1c | |||
| 98ba871a71 | |||
| 3ff23c0264 | |||
| e21f89477b | |||
| f177f514f5 | |||
| af30f3b348 | |||
| 82df618429 | |||
| bb3538e270 | |||
| 71925e1126 | |||
| 93c1cbd231 | |||
| 894b890fe5 | |||
| 8e9e8f7fad | |||
| 2a0461a76f | |||
| 85f923a6fc | |||
| b35e4d4d01 | |||
| cb24a859f4 | |||
| b1ef00746f | |||
| aebe82e3a7 | |||
| 7c87856b4d | |||
| d1b1dd539f | |||
| 55eea88ace | |||
| a70f64e1f6 | |||
| fa0cb120a7 | |||
| e3080d07dc | |||
| 34726c533e | |||
| 4a0d72d2cc | |||
| fe3fc5c9f7 | |||
| 441228e2b0 | |||
| 7538aee4f2 | |||
| acf809268e | |||
| 4ebc0c10b6 | |||
| a453888ca2 | |||
| 530b44762b | |||
| f85587fb0b | |||
| edb8799b1a | |||
| e47aeb37f0 | |||
| 776e9968dc | |||
| 1898bf4731 | |||
| 78df020737 | |||
| b93f9a4b9a | |||
| 748b230ef5 | |||
| deb8dde9e1 | |||
| dbb2f10754 | |||
| 0ded03ab92 | |||
| 2198e84f3b | |||
| 14d44528b0 | |||
| eb8159ca0f | |||
| 9811f40a53 | |||
| 8de7e13aa3 | |||
| c63e6a1e49 | |||
| 5a21d2cb10 | |||
| 424c0e596c | |||
| d431b63c27 | |||
| 38c2781cd3 | |||
| 796fb348a3 | |||
| 71b306d5fd | |||
| 4c610ea32d | |||
| 4bff006743 | |||
| 1645079bc0 | |||
| 9afb58e4a7 | |||
| 2820fc8acf | |||
| 4d77a498f6 | |||
| d77de3bb12 | |||
| 29e7ad6ce6 | |||
| 1712b5120e | |||
| 06c0153cf5 | |||
| 44f7ecda6d | |||
| fb94bf1b80 | |||
| 4818652582 | |||
| c69b9784fc | |||
| 0ac244a3ea | |||
| 19a445fdab | |||
| c90a18a2c0 | |||
| 502310c413 | |||
| 6f9424d4ec | |||
| bb379fe667 | |||
| 0fd86bf214 | |||
| 29b75d4391 | |||
| a7124e5449 | |||
| a714f3480a | |||
| c10e0df898 | |||
| fba734fd5a | |||
| 27e2372097 | |||
| 7f5b99495c | |||
| 1efe2a56af | |||
| 850873aec8 | |||
| d9e6afbf36 | |||
| 7f3bd2715c | |||
| c81cb393e9 | |||
| 4800faa783 | |||
| 1087b5e1d1 | |||
| 5dc2e71976 | |||
| 28eb7d0810 | |||
| c641a92d89 | |||
| 3e57cc045f | |||
| c60a8ddf66 | |||
| 8becef3e45 | |||
| 3237634e3b | |||
| 2a4a659e39 | |||
| fcaa47c0a8 | |||
| 68ea17ccbd | |||
| 80308c7102 | |||
| 6f4a99a7cb | |||
| ac245f5128 | |||
| 7f9e9e27a0 | |||
| abf58a4aec | |||
| 5d9a700a6e | |||
| 3662b1eb1d | |||
| 34449da2b8 | |||
| 42f367f822 | |||
| 781ca0bb77 | |||
| ebe5d50dae | |||
| 00d6dc5626 | |||
| a1648c307f | |||
| b8f170ae39 | |||
| 073f1da5b4 | |||
| 6310711136 | |||
| fcac7a4ce1 | |||
| c2b1aef810 | |||
| c8ab26275c | |||
| a1fd6a2b6b | |||
| 561c08e0cc | |||
| 4658e30e89 | |||
| 225e6b369a | |||
| 0e9094a19f | |||
| 2da0e03c6c | |||
| 9a6fac5fc8 | |||
| b541f0a896 | |||
| cec7cce077 | |||
| fb13695ca5 | |||
| 20c76d06f7 | |||
| 339a11f649 | |||
| 0989400d87 | |||
| 52aacf602d | |||
| 54d70a6a17 | |||
| d980e09e0f | |||
| 2e4cb12817 | |||
| 7b91cb2e96 | |||
| 95c04a8abc | |||
| 25822fefdb | |||
| d800ee2d28 | |||
| 2a51371aca | |||
| ee5d1a47dc | |||
| b330b74347 | |||
| 11fa13f0bb | |||
| 21400d72b3 | |||
| a710cb9d4f | |||
| 3326ad52ce | |||
| c9560df851 | |||
| 74cb45118e | |||
| c79bf19e51 | |||
| 961bec0a2f | |||
| 89e4977cd1 | |||
| bfe16475db | |||
| 915d36867c | |||
| 48435af407 | |||
| 86b6ec5212 | |||
| 775e70bc45 | |||
| 9f565447d0 | |||
| 88d27bc29d | |||
| 172ae87ac6 | |||
| 91d572235e | |||
| 64d32dcb75 | |||
| 564b4283b6 | |||
| ca4d374a81 | |||
| a753806d7b | |||
| bd1692cea3 | |||
| b7ce089f08 | |||
| 8a6b47c5db | |||
| 9f1fc4df18 | |||
| c018a2a7bc | |||
| a1aebab114 | |||
| e30702e1d8 | |||
| 008ff4b055 | |||
| d7bba22e19 | |||
| 2b9a910533 | |||
| 118ebcc627 | |||
| c741767b11 | |||
| 4a09358e14 | |||
| 3f4ea1af08 | |||
| 35bb196832 | |||
| cb5b50dd42 | |||
| 8652272526 | |||
| 0f32504fde | |||
| 4735c21fc0 | |||
| ecbcbcaed4 | |||
| 1677b73ff8 | |||
| 5929067a3d | |||
| d06834617b | |||
| 9d048efe06 | |||
| 6a379bc2cd | |||
| 9f415b11b5 | |||
| b9b9193222 | |||
| 867c2d1632 | |||
| 5447afc3f5 | |||
| b5e58db242 | |||
| 8ab99619d6 | |||
| 4c7660ee65 | |||
| c1b9bde7b0 | |||
| 0e8c6c066f | |||
| 9e44a86be0 | |||
| b61479f84f | |||
| e3c709b005 | |||
| b2b3dba504 | |||
| 4d05441aa8 | |||
| 419b3ee850 | |||
| 4c31e72d29 | |||
| e3b2ff7f0e | |||
| 4c5f5e2cce | |||
| 39ae9b8ba0 | |||
| 5c7eb0535d | |||
| 235718390b | |||
| 5d4b72f224 | |||
| dc76ae9d1f | |||
| e44f4bb003 | |||
| 1fc1370d41 | |||
| 80a669c989 | |||
| 801c9eba2d | |||
| f9704d2836 | |||
| 39687171e9 | |||
| 1d73691ef4 | |||
| f8678d2515 | |||
| fb108ea18d | |||
| a7229a0677 | |||
| d0dd112b98 | |||
| 1e07120eb5 | |||
| fcd1f76cff | |||
| e400d86d75 | |||
| dca3410a5b | |||
| 9b314e2953 | |||
| 5635daf66d | |||
| 7e2e1645e9 | |||
| 4990afcdbb | |||
| c11f36dfef | |||
| abddf61c88 | |||
| 37fec7e952 | |||
| 0f6a93ae8f | |||
| 25eae334b0 | |||
| 74377d01ce | |||
| 6e78ba1e7b | |||
| 39e0dedf27 | |||
| bbe2c88802 | |||
| 586b31b63e | |||
| 041abe6d7e | |||
| a69b3cd05f | |||
| b48213e79e | |||
| 5bbc14aca5 | |||
| 8ccbf502e8 | |||
| c426ca97e2 | |||
| d9eef86a8b | |||
| 3fed921748 | |||
| 02827d53a2 | |||
| 1ad5fde9ae | |||
| 909d5ed99c | |||
| b9096df218 | |||
| 1137485c55 | |||
| 61b1155a03 | |||
| 35624bcb1c | |||
| 6e262334ed | |||
| 829d69485a | |||
| 0d32c168eb | |||
| 38d6d93f65 | |||
| 9a280492c2 | |||
| d49ee79c90 | |||
| 73b83af6b1 | |||
| 064673ef23 | |||
| 81bf93e5ab | |||
| 26d5a8ce08 | |||
| c6f5c8d91f | |||
| 63a1928468 | |||
| 27c2aee8b9 | |||
| 5219d29aca | |||
| 84955352dd | |||
| 8e05c30063 | |||
| 6f98bcafec | |||
| 4afac91bce | |||
| 6e6312f6d7 | |||
| df4c4e443d | |||
| ff40474f92 | |||
| aca06ee805 | |||
| ba8e29a9f8 | |||
| 583da2bd9f | |||
| 0ea07016b4 | |||
| 616421db9a | |||
| 293ddacd19 | |||
| 13945ec937 | |||
| 4ea6f336f8 | |||
| 58296aa266 | |||
| 742df9dff3 | |||
| 011e1f5922 | |||
| 8f67d69325 | |||
| 9ac133b605 | |||
| 538b2d26cd | |||
| cc3895c423 | |||
| 79454bfc3b | |||
| 734c7572bb | |||
| 9f93fbb161 | |||
| c78c63285e | |||
| c8cbf70a28 | |||
| 2b116d6756 | |||
| da611153cf | |||
| fd9bf4468a | |||
| fa234eb9d6 | |||
| dbfebf6a32 | |||
| 7b91e31485 | |||
| e882fc8b5e | |||
| 5a54195cac | |||
| a442adf8d5 | |||
| 38466878db | |||
| 7c86e4e743 | |||
| 41cbfb8d39 | |||
| 7c394f4b20 | |||
| c1a35e1053 | |||
| cddce8596f | |||
| c75058b1da | |||
| 1a73fcdb39 | |||
| 8e0c4f5308 | |||
| 51e2791cc7 | |||
| 130159f06c | |||
| 42d1140b55 | |||
| dfd987041a | |||
| 790d1787fd | |||
| 2a6a607c7b | |||
| b3521d2a18 | |||
| dee99caa7d | |||
| cf525a3929 | |||
| 18d658f7e1 | |||
| 1c42ab77d8 | |||
| 33d5638bb0 | |||
| 8ce92df87a | |||
| 80654449af | |||
| eee1622801 | |||
| 4c54876ecf | |||
| 1cbcd5c2da | |||
| 55253e284e | |||
| e9795cd697 | |||
| be76d9a6dc | |||
| d7cdaf2870 | |||
| 48ed0e01d1 | |||
| dca31dedde | |||
| ab7356b991 | |||
| a46a673cf8 | |||
| c8d52539ca | |||
| ed9267b6ba | |||
| b7c02d1cf8 | |||
| fb66beb29f | |||
| 8c3bf6bbc3 | |||
| b943078132 | |||
| e727617bf1 | |||
| ffaea6dcbe | |||
| bf1f72a2a4 | |||
| be0df7c5b0 | |||
| 5ab769e74d | |||
| d22ddb1731 | |||
| 9fed8c022b | |||
| a315ed90af | |||
| 1ebf3c9af2 | |||
| 0e4c923c23 | |||
| 63835b9f99 | |||
| ff17f7c132 | |||
| f4631c9b38 | |||
| 35931023ae | |||
| 6d93381760 | |||
| f1bdd5f1b2 | |||
| 1c3e2fbad7 | |||
| 29a02db07d | |||
| f1db1ba708 | |||
| c1420bac88 | |||
| 8e527fbbdf | |||
| 5ec1bcfe3f | |||
| 7226461cd0 | |||
| 6d6f383c92 | |||
| e1a6328d09 | |||
| 6e4153911a | |||
| 342f74646e | |||
| fe5191d3b5 | |||
| 504cf97c6c | |||
| f8c494c9c1 | |||
| b90d7f721a | |||
| 7936af6c9a | |||
| 52d01e3dd7 | |||
| d30d70395a | |||
| 491a3ae525 | |||
| 1eae380b08 | |||
| f091b2526e | |||
| 7548e2e202 | |||
| d9b9afbf2d | |||
| 8036659003 | |||
| f9fb4668c2 | |||
| 7047924947 | |||
| 8f6be3911a | |||
| 0d95b8eb44 | |||
| 61d2d124ff | |||
| 7b218b2544 | |||
| 87ac7daf76 | |||
| 6b4817df36 | |||
| 22d99da2e1 | |||
| 47b6cf7068 | |||
| 606c9512f8 | |||
| aef9c591e9 | |||
| 71f67e9191 | |||
| 636f2b3017 | |||
| 2de5b5c6e4 | |||
| 0cbcc8c9f3 | |||
| 96146e3dc8 | |||
| 5aaae51be1 | |||
| b98625fdbc | |||
| 09a748e9dc | |||
| 87b07c6d5b | |||
| f39e668f8d | |||
| 6ea95342a0 | |||
| c594bf5757 | |||
| cd3b198c6f | |||
| b249b5f46e | |||
| bbe3b48bcc | |||
| 3bcd056197 | |||
| 6387ab41b3 | |||
| 4df16b7f15 | |||
| ed387a2873 | |||
| 9e225530a6 | |||
| 7b23686dc6 | |||
| 4de31453fd | |||
| 4c59526e39 | |||
| 9ec1764194 | |||
| 47afa32902 | |||
| 2a09487b55 | |||
| 563c856dd3 | |||
| 69ea242408 | |||
| d6e0e0726f | |||
| 73d460d40a | |||
| 1f27d96ac9 | |||
| 93e9f28d69 | |||
| ec2e26752a | |||
| fadd95f3e6 | |||
| 00acc677e6 | |||
| 1a799881e8 | |||
| f75677593a | |||
| 19e3bd19f0 | |||
| 85701b0a3c | |||
| 014cb18dcb | |||
| e71e1c853f | |||
| ee9d9196f5 | |||
| 53c8272e01 | |||
| 7f7b6b1e2a | |||
| 405777e0f5 | |||
| df2b624cb5 | |||
| 8a48d5c2f9 | |||
| c55ee71442 | |||
| 3f82745f5b | |||
| 404187a1ae | |||
| 2b7b3f586b | |||
| 04959a3493 | |||
| 97cf4932ae | |||
| b0d88a0a37 | |||
| 67a2e40622 | |||
| 3a28556c7f | |||
| 9ecc92b9a5 | |||
| ca023be98a | |||
| 11a1423f76 | |||
| 79f6df121b | |||
| 71eade7e86 | |||
| 5f81d29036 | |||
| ec1cb5dc5f | |||
| fd969e2d55 | |||
| 37e33b77ff | |||
| f7ed7703b4 | |||
| 4bb35295ca | |||
| 1e4f673f9e | |||
| 7cadb1c403 | |||
| 37148f5093 | |||
| f6bc26789f | |||
| b3f5a88525 | |||
| 1e538d2b28 | |||
| 7d7bfb7b01 | |||
| 41d86ba440 | |||
| 3df474a8a5 | |||
| a50d6e8f47 | |||
| 6081e5b9c1 | |||
| 66ccea920c | |||
| 470d63093f | |||
| eae0507831 | |||
| 92af85d3bb | |||
| 7635af5730 | |||
| a838e89695 | |||
| b22289a8b9 | |||
| 45b3ff52c6 | |||
| 4464991f4c | |||
| b0d2f77583 | |||
| b211a4405d | |||
| 8823016d2c | |||
| 859fdc7ec1 | |||
| 028d5ed01f | |||
| 5fd5a2a436 | |||
| 79a7e7470c | |||
| 9ecef78aed | |||
| 65a837a6e1 | |||
| 6e4db4acea | |||
| 26fb977d05 | |||
| b42cd1c048 | |||
| 467f7cd12f | |||
| 66699ce9df | |||
| cf7d903932 | |||
| a7ab67925c | |||
| a474ba4260 | |||
| 09e5636e86 | |||
| 2295a875be | |||
| 82a2455afc | |||
| 268de676ee | |||
| 8fe26c07f1 | |||
| da3921b1ca | |||
| 4dd2e787d1 | |||
| ce005ae6c2 | |||
| 1513f46a11 | |||
| 7543eeb0f4 | |||
| 873242120c | |||
| 98f8095a65 | |||
| 785571a550 | |||
| 0c4bd4044e | |||
| 0319543dce | |||
| 82d70b2d7f | |||
| 62d18e010a | |||
| fc77b85083 | |||
| 50a8893f4f | |||
| 9252b3040e | |||
| d5141ed020 | |||
| 7ff9e23283 | |||
| 89854d527c | |||
| 6ff0cad2a8 | |||
| 349cfbd2d5 | |||
| 40303ef74a | |||
| 6c652122c2 | |||
| 3658e3a2aa | |||
| 2b20fcfcd1 | |||
| 554d427fef | |||
| 7cf5b23306 | |||
| b26a6098eb | |||
| 7ad927bdaf | |||
| 4ed30b3619 | |||
| edfa9264d5 | |||
| f7516b593f | |||
| 83ff998f9d | |||
| 47381e0df4 | |||
| ba62d57485 | |||
| c014c4bc24 | |||
| 5d1a3fede2 | |||
| 53b584fe45 | |||
| f53d974400 | |||
| c4b4ef19cd | |||
| 3bfc360362 | |||
| 584f16d375 | |||
| b3d84c3217 | |||
| dd14ad470e | |||
| 85b90574b8 | |||
| ee5d172468 | |||
| 7ca4b94361 | |||
| 31f1546483 | |||
| d8a88a19af | |||
| 12af79de05 | |||
| 2260dd419d | |||
| 61a940cc82 | |||
| 1bbc1e0d7e | |||
| 921294eeb3 | |||
| baaa90f49d | |||
| 4e25381770 | |||
| 272877d0ed | |||
| 555b947bf7 | |||
| da29811b16 | |||
| 241f67fd4d | |||
| eb4ce18e31 | |||
| ae99fee440 | |||
| d116ac5e56 | |||
| 28db1f4253 | |||
| 034312e676 | |||
| da83d73ba6 | |||
| 02e8dc3440 | |||
| cac6d1f889 | |||
| 68fa3294d4 | |||
| 9b983de8c9 | |||
| 3a37ee719b | |||
| 61359c2faa | |||
| 7f7c5ab35b | |||
| a1b483d20a | |||
| 04cd662d78 | |||
| da597f076f | |||
| fab3efdcf5 | |||
| a55509a34d | |||
| 84fb1c5b2b | |||
| 391a90e1df | |||
| e0fe39195d | |||
| 385fead81a | |||
| 648d1b9aa9 | |||
| 3f0028913d | |||
| 45e6ec8b0f | |||
| a3fbaa0b34 | |||
| 7102cbfb3b | |||
| c3db3ce0f2 | |||
| 7a1e7637ff | |||
| 04a78a02d3 | |||
| cb61dc742f | |||
| cd53f6e757 | |||
| c64f7daa8d | |||
| e70d792654 | |||
| 9ae533f907 | |||
| cfe92f18e3 | |||
| e2a34ea28e | |||
| ec8000360e | |||
| 57b0821e19 | |||
| 09d39df15a | |||
| 1f9db3bda6 | |||
| b7104c8828 | |||
| 5da02b4092 | |||
| 802f1e3042 | |||
| 66db0df45a | |||
| 650c2e2eb7 | |||
| 6ab3754129 | |||
| 7dca0a8cab | |||
| 7cd0b4ad54 | |||
| 97acb41eee | |||
| b916b9726e | |||
| 32d3990ace | |||
| cb1fd109cc | |||
| 0e68dd6185 | |||
| fb6502bc65 | |||
| c7e7403781 | |||
| bf224408a3 | |||
| 84b7078873 | |||
| 89e5943d8f | |||
| b78c4cb8f0 | |||
| 976ba074a8 | |||
| 5205d59b96 | |||
| e8394b9c08 | |||
| 9cd00239f9 | |||
| b6b26142f8 | |||
| 4ee99376fd | |||
| b0261342ff | |||
| 87fd2a521e | |||
| 334793c6f6 | |||
| 3e70d991bb | |||
| feec96fc5c | |||
| 765984709e | |||
| c7c9931f68 | |||
| ae64573510 | |||
| d675af5aa4 | |||
| 9480d17cfc | |||
| 5ac1df2283 |
107
.gitignore
vendored
107
.gitignore
vendored
@@ -1,6 +1,12 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# TweetDuck installer builds
|
||||||
|
bld/*
|
||||||
|
!bld/*.iss
|
||||||
|
!bld/*.bat
|
||||||
|
!bld/Resources
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
@@ -19,15 +25,9 @@ x64/
|
|||||||
x86/
|
x86/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
bld/*
|
|
||||||
!bld/gen_full.iss
|
|
||||||
!bld/gen_upd.iss
|
|
||||||
!bld/Resources
|
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
||||||
#wwwroot/
|
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
@@ -37,11 +37,6 @@ bld/*
|
|||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# DNX
|
# DNX
|
||||||
project.lock.json
|
project.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
@@ -70,27 +65,12 @@ artifacts/
|
|||||||
*.svclog
|
*.svclog
|
||||||
*.scc
|
*.scc
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
*.sap
|
*.sap
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
# Guidance Automation Toolkit
|
||||||
*.gpState
|
*.gpState
|
||||||
|
|
||||||
@@ -117,33 +97,9 @@ nCrunchTemp_*
|
|||||||
*.mm.*
|
*.mm.*
|
||||||
AutoTest.Net/
|
AutoTest.Net/
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
# Click-Once directory
|
||||||
publish/
|
publish/
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
@@ -156,17 +112,6 @@ publish/
|
|||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Microsoft Azure ApplicationInsights config file
|
|
||||||
ApplicationInsights.config
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
# Windows Store app package directory
|
||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
@@ -188,9 +133,6 @@ ClientBin/
|
|||||||
node_modules/
|
node_modules/
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
# Backup & report files from converting an old project file
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
# because we have git ;-)
|
# because we have git ;-)
|
||||||
@@ -199,40 +141,3 @@ Backup*/
|
|||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|||||||
46
Configuration/Arguments.cs
Normal file
46
Configuration/Arguments.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
|
||||||
|
namespace TweetDuck.Configuration{
|
||||||
|
static class Arguments{
|
||||||
|
// public args
|
||||||
|
public const string ArgDataFolder = "-datafolder";
|
||||||
|
public const string ArgLocale = "-locale";
|
||||||
|
public const string ArgLogging = "-log";
|
||||||
|
public const string ArgDebugUpdates = "-debugupdates";
|
||||||
|
|
||||||
|
// internal args
|
||||||
|
public const string ArgRestart = "-restart";
|
||||||
|
public const string ArgImportCookies = "-importcookies";
|
||||||
|
public const string ArgUpdated = "-updated";
|
||||||
|
|
||||||
|
// class data and methods
|
||||||
|
private static readonly CommandLineArgs Current = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs());
|
||||||
|
|
||||||
|
public static bool HasFlag(string flag){
|
||||||
|
return Current.HasFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetValue(string key, string defaultValue){
|
||||||
|
return Current.GetValue(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommandLineArgs GetCurrentClean(){
|
||||||
|
CommandLineArgs args = Current.Clone();
|
||||||
|
args.RemoveFlag(ArgRestart);
|
||||||
|
args.RemoveFlag(ArgImportCookies);
|
||||||
|
args.RemoveFlag(ArgUpdated);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommandLineArgs GetCurrentForInstaller(){
|
||||||
|
CommandLineArgs args = GetCurrentClean();
|
||||||
|
args.AddFlag(ArgUpdated);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCurrentForInstallerCmd(){
|
||||||
|
return GetCurrentForInstaller().ToString().Replace("\"", "::");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,124 +1,189 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetLib.Communication;
|
||||||
|
|
||||||
namespace TweetDck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
sealed class LockManager{
|
sealed class LockManager{
|
||||||
public Process LockingProcess { get; private set; }
|
private const int RetryDelay = 250;
|
||||||
|
|
||||||
|
public enum Result{
|
||||||
|
Success, HasProcess, Fail
|
||||||
|
}
|
||||||
|
|
||||||
private readonly string file;
|
private readonly string file;
|
||||||
private FileStream lockStream;
|
private FileStream lockStream;
|
||||||
|
private Process lockingProcess;
|
||||||
|
|
||||||
public LockManager(string file){
|
public LockManager(string file){
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CreateLockFile(){
|
// Lock file
|
||||||
|
|
||||||
|
private bool ReleaseLockFileStream(){
|
||||||
if (lockStream != null){
|
if (lockStream != null){
|
||||||
throw new InvalidOperationException("Lock file already exists.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
|
||||||
lockStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
|
|
||||||
|
|
||||||
byte[] id = BitConverter.GetBytes(Process.GetCurrentProcess().Id);
|
|
||||||
lockStream.Write(id, 0, id.Length);
|
|
||||||
lockStream.Flush();
|
|
||||||
|
|
||||||
if (LockingProcess != null){
|
|
||||||
LockingProcess.Close();
|
|
||||||
LockingProcess = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}catch(Exception){
|
|
||||||
if (lockStream != null){
|
|
||||||
lockStream.Close();
|
|
||||||
lockStream.Dispose();
|
lockStream.Dispose();
|
||||||
|
lockStream = null;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Lock(){
|
private Result TryCreateLockFile(){
|
||||||
if (lockStream != null)return true;
|
void CreateLockFileStream(){
|
||||||
|
lockStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||||
try{
|
lockStream.Write(BitConverter.GetBytes(WindowsUtils.CurrentProcessID), 0, sizeof(int));
|
||||||
byte[] bytes = new byte[4];
|
lockStream.Flush(true);
|
||||||
|
|
||||||
using(FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
|
|
||||||
fileStream.Read(bytes, 0, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pid = BitConverter.ToInt32(bytes, 0);
|
try{
|
||||||
|
CreateLockFileStream();
|
||||||
|
return Result.Success;
|
||||||
|
}catch(DirectoryNotFoundException){
|
||||||
|
try{
|
||||||
|
CreateLockFileStream();
|
||||||
|
return Result.Success;
|
||||||
|
}catch{
|
||||||
|
ReleaseLockFileStream();
|
||||||
|
return Result.Fail;
|
||||||
|
}
|
||||||
|
}catch(IOException){
|
||||||
|
return Result.HasProcess;
|
||||||
|
}catch{
|
||||||
|
ReleaseLockFileStream();
|
||||||
|
return Result.Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock management
|
||||||
|
|
||||||
|
public Result Lock(){
|
||||||
|
if (lockStream != null){
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result initialResult = TryCreateLockFile();
|
||||||
|
|
||||||
|
if (initialResult == Result.HasProcess){
|
||||||
|
try{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
using(FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
|
||||||
|
byte[] bytes = new byte[sizeof(int)];
|
||||||
|
fileStream.Read(bytes, 0, bytes.Length);
|
||||||
|
pid = BitConverter.ToInt32(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Process foundProcess = Process.GetProcessById(pid);
|
Process foundProcess = Process.GetProcessById(pid);
|
||||||
|
|
||||||
using(Process currentProcess = Process.GetCurrentProcess()){
|
using(Process currentProcess = Process.GetCurrentProcess()){
|
||||||
if (foundProcess.ProcessName == currentProcess.ProcessName){
|
if (foundProcess.MainModule.FileVersionInfo.InternalName == currentProcess.MainModule.FileVersionInfo.InternalName){
|
||||||
LockingProcess = foundProcess;
|
lockingProcess = foundProcess;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
foundProcess.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(ArgumentException){}
|
}catch{
|
||||||
|
// GetProcessById throws ArgumentException if the process is missing
|
||||||
return LockingProcess == null && CreateLockFile();
|
// Process.MainModule can throw exceptions in some cases
|
||||||
}catch(DirectoryNotFoundException){
|
|
||||||
string dir = Path.GetDirectoryName(file);
|
|
||||||
|
|
||||||
if (dir != null){
|
|
||||||
Directory.CreateDirectory(dir);
|
|
||||||
return CreateLockFile();
|
|
||||||
}
|
|
||||||
}catch(FileNotFoundException){
|
|
||||||
return CreateLockFile();
|
|
||||||
}catch(Exception){
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return lockingProcess == null ? Result.Fail : Result.HasProcess;
|
||||||
|
}catch{
|
||||||
|
return Result.Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result LockWait(int timeout){
|
||||||
|
for(int elapsed = 0; elapsed < timeout; elapsed += RetryDelay){
|
||||||
|
Result result = Lock();
|
||||||
|
|
||||||
|
if (result == Result.HasProcess){
|
||||||
|
Thread.Sleep(RetryDelay);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Unlock(){
|
public bool Unlock(){
|
||||||
bool result = true;
|
if (ReleaseLockFileStream()){
|
||||||
|
|
||||||
if (lockStream != null){
|
|
||||||
lockStream.Dispose();
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Program.Reporter.Log(e.ToString());
|
Program.Reporter.Log(e.ToString());
|
||||||
result = false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lockStream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CloseLockingProcess(int timeout){
|
|
||||||
if (LockingProcess != null){
|
|
||||||
LockingProcess.CloseMainWindow();
|
|
||||||
|
|
||||||
for(int waited = 0; waited < timeout && !LockingProcess.HasExited;){
|
|
||||||
LockingProcess.Refresh();
|
|
||||||
|
|
||||||
Thread.Sleep(100);
|
|
||||||
waited += 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LockingProcess.HasExited){
|
|
||||||
LockingProcess.Dispose();
|
|
||||||
LockingProcess = null;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locking process
|
||||||
|
|
||||||
|
public bool RestoreLockingProcess(int failTimeout){
|
||||||
|
if (lockingProcess != null){
|
||||||
|
if (lockingProcess.MainWindowHandle == IntPtr.Zero){ // restore if the original process is in tray
|
||||||
|
Comms.BroadcastMessage(Program.WindowRestoreMessage, (uint)lockingProcess.Id, 0);
|
||||||
|
|
||||||
|
if (WindowsUtils.TrySleepUntil(() => CheckLockingProcessExited() || (lockingProcess.MainWindowHandle != IntPtr.Zero && lockingProcess.Responding), failTimeout, RetryDelay)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CloseLockingProcess(int closeTimeout, int killTimeout){
|
||||||
|
if (lockingProcess != null){
|
||||||
|
try{
|
||||||
|
if (lockingProcess.CloseMainWindow()){
|
||||||
|
WindowsUtils.TrySleepUntil(CheckLockingProcessExited, closeTimeout, RetryDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lockingProcess.HasExited){
|
||||||
|
lockingProcess.Kill();
|
||||||
|
WindowsUtils.TrySleepUntil(CheckLockingProcessExited, killTimeout, RetryDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockingProcess.HasExited){
|
||||||
|
lockingProcess.Dispose();
|
||||||
|
lockingProcess = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}catch(Exception ex){
|
||||||
|
if (ex is InvalidOperationException || ex is Win32Exception){
|
||||||
|
if (lockingProcess != null){
|
||||||
|
bool hasExited = CheckLockingProcessExited();
|
||||||
|
lockingProcess.Dispose();
|
||||||
|
return hasExited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckLockingProcessExited(){
|
||||||
|
lockingProcess.Refresh();
|
||||||
|
return lockingProcess.HasExited;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
Configuration/SystemConfig.cs
Normal file
73
Configuration/SystemConfig.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Data.Serialization;
|
||||||
|
|
||||||
|
namespace TweetDuck.Configuration{
|
||||||
|
sealed class SystemConfig{
|
||||||
|
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>{
|
||||||
|
// HandleUnknownProperties = (obj, data) => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
||||||
|
File.Exists(Path.Combine(Program.ProgramPath, "libGLESv2.dll"));
|
||||||
|
|
||||||
|
// CONFIGURATION DATA
|
||||||
|
|
||||||
|
private bool _hardwareAcceleration = true;
|
||||||
|
|
||||||
|
public bool EnableBrowserGCReload { get; set; } = true;
|
||||||
|
public int BrowserMemoryThreshold { get; set; } = 400;
|
||||||
|
|
||||||
|
// SPECIAL PROPERTIES
|
||||||
|
|
||||||
|
public bool HardwareAcceleration{
|
||||||
|
get => _hardwareAcceleration && IsHardwareAccelerationSupported;
|
||||||
|
set => _hardwareAcceleration = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// END OF CONFIG
|
||||||
|
|
||||||
|
private readonly string file;
|
||||||
|
|
||||||
|
private SystemConfig(string file){
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Save(){
|
||||||
|
try{
|
||||||
|
WindowsUtils.CreateDirectoryForFile(file);
|
||||||
|
Serializer.Write(file, this);
|
||||||
|
return true;
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not save the system configuration file.", true, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SystemConfig Load(string file){
|
||||||
|
SystemConfig config = new SystemConfig(file);
|
||||||
|
|
||||||
|
try{
|
||||||
|
Serializer.Read(file, config);
|
||||||
|
return config;
|
||||||
|
}catch(FileNotFoundException){
|
||||||
|
}catch(DirectoryNotFoundException){
|
||||||
|
}catch(FormatException){
|
||||||
|
try{
|
||||||
|
using(Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)){
|
||||||
|
config.HardwareAcceleration = stream.ReadByte() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Save();
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not update the system configuration file.", true, e);
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not open the system configuration file. If you continue, you will lose system specific configuration such as Hardware Acceleration.", true, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,181 +1,165 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using TweetDuck.Core;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Core;
|
using TweetDuck.Core.Notification;
|
||||||
using TweetDck.Core.Handling;
|
using TweetDuck.Core.Utils;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Data;
|
||||||
using TweetDck.Plugins;
|
using TweetDuck.Data.Serialization;
|
||||||
|
|
||||||
namespace TweetDck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
[Serializable]
|
|
||||||
sealed class UserConfig{
|
sealed class UserConfig{
|
||||||
private static readonly IFormatter Formatter = new BinaryFormatter{
|
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>{ HandleUnknownProperties = HandleUnknownProperties };
|
||||||
Binder = new SerializationCompatibilityHandler()
|
|
||||||
};
|
|
||||||
|
|
||||||
private const int CurrentFileVersion = 5;
|
private static void HandleUnknownProperties(UserConfig obj, Dictionary<string, string> data){
|
||||||
|
if (data.TryGetValue("EnableBrowserGCReload", out string propGCReload) && data.TryGetValue("BrowserMemoryThreshold", out string propMemThreshold)){
|
||||||
// START OF CONFIGURATION
|
if (bool.TryParse(propGCReload, out bool isGCReloadEnabled) && isGCReloadEnabled && int.TryParse(propMemThreshold, out int memThreshold)){
|
||||||
|
// SystemConfig initialization was moved before UserConfig to allow for this
|
||||||
public bool IgnoreMigration { get; set; }
|
// TODO remove the migration soon
|
||||||
public bool IgnoreUninstallCheck { get; set; }
|
Program.SystemConfig.EnableBrowserGCReload = true;
|
||||||
|
Program.SystemConfig.BrowserMemoryThreshold = memThreshold;
|
||||||
public WindowState BrowserWindow { get; set; }
|
Program.SystemConfig.Save();
|
||||||
public bool DisplayNotificationTimer { get; set; }
|
|
||||||
public bool NotificationTimerCountDown { get; set; }
|
|
||||||
|
|
||||||
public TweetNotification.Duration NotificationDuration { get; set; }
|
|
||||||
public TweetNotification.Position NotificationPosition { get; set; }
|
|
||||||
public Point CustomNotificationPosition { get; set; }
|
|
||||||
public int NotificationEdgeDistance { get; set; }
|
|
||||||
public int NotificationDisplay { get; set; }
|
|
||||||
public int NotificationDurationValue { get; set; }
|
|
||||||
public bool NotificationLegacyLoad { get; set; }
|
|
||||||
|
|
||||||
public bool EnableSpellCheck { get; set; }
|
|
||||||
public bool ExpandLinksOnHover { get; set; }
|
|
||||||
public bool EnableTrayHighlight { get; set; }
|
|
||||||
|
|
||||||
public bool EnableUpdateCheck { get; set; }
|
|
||||||
public string DismissedUpdate { get; set; }
|
|
||||||
|
|
||||||
public PluginConfig Plugins { get; private set; }
|
|
||||||
public WindowState PluginsWindow { get; set; }
|
|
||||||
|
|
||||||
public string CustomCefArgs { get; set; }
|
|
||||||
public string CustomBrowserCSS { get; set; }
|
|
||||||
public string CustomNotificationCSS { get; set; }
|
|
||||||
|
|
||||||
public bool IsCustomNotificationPositionSet{
|
|
||||||
get{
|
|
||||||
return CustomNotificationPosition.X != -32000 && CustomNotificationPosition.X != 32000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.Remove("EnableBrowserGCReload");
|
||||||
|
data.Remove("BrowserMemoryThreshold");
|
||||||
|
|
||||||
|
if (data.Count == 0){
|
||||||
|
obj.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UserConfig(){
|
||||||
|
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
|
||||||
|
|
||||||
|
Serializer.RegisterTypeConverter(typeof(Point), new SingleTypeConverter<Point>{
|
||||||
|
ConvertToString = value => $"{value.X} {value.Y}",
|
||||||
|
ConvertToObject = value => {
|
||||||
|
int[] elements = StringUtils.ParseInts(value, ' ');
|
||||||
|
return new Point(elements[0], elements[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Serializer.RegisterTypeConverter(typeof(Size), new SingleTypeConverter<Size>{
|
||||||
|
ConvertToString = value => $"{value.Width} {value.Height}",
|
||||||
|
ConvertToObject = value => {
|
||||||
|
int[] elements = StringUtils.ParseInts(value, ' ');
|
||||||
|
return new Size(elements[0], elements[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONFIGURATION DATA
|
||||||
|
|
||||||
|
public WindowState BrowserWindow { get; set; } = new WindowState();
|
||||||
|
public WindowState PluginsWindow { get; set; } = new WindowState();
|
||||||
|
|
||||||
|
public bool ExpandLinksOnHover { get; set; } = true;
|
||||||
|
public bool SwitchAccountSelectors { get; set; } = true;
|
||||||
|
public bool BestImageQuality { get; set; } = true;
|
||||||
|
public bool EnableSpellCheck { get; set; } = false;
|
||||||
|
public int VideoPlayerVolume { get; set; } = 50;
|
||||||
|
private int _zoomLevel = 100;
|
||||||
|
private bool _muteNotifications;
|
||||||
|
|
||||||
|
private TrayIcon.Behavior _trayBehavior = TrayIcon.Behavior.Disabled;
|
||||||
|
public bool EnableTrayHighlight { get; set; } = true;
|
||||||
|
|
||||||
|
public bool EnableUpdateCheck { get; set; } = true;
|
||||||
|
public string DismissedUpdate { get; set; } = null;
|
||||||
|
|
||||||
|
public bool DisplayNotificationColumn { get; set; } = false;
|
||||||
|
public bool NotificationMediaPreviews { get; set; } = true;
|
||||||
|
public bool NotificationSkipOnLinkClick { get; set; } = false;
|
||||||
|
public bool NotificationNonIntrusiveMode { get; set; } = true;
|
||||||
|
public int NotificationIdlePauseSeconds { get; set; } = 0;
|
||||||
|
|
||||||
|
public bool DisplayNotificationTimer { get; set; } = true;
|
||||||
|
public bool NotificationTimerCountDown { get; set; } = false;
|
||||||
|
public int NotificationDurationValue { get; set; } = 25;
|
||||||
|
|
||||||
|
public TweetNotification.Position NotificationPosition { get; set; } = TweetNotification.Position.TopRight;
|
||||||
|
public Point CustomNotificationPosition { get; set; } = ControlExtensions.InvisibleLocation;
|
||||||
|
public int NotificationDisplay { get; set; } = 0;
|
||||||
|
public int NotificationEdgeDistance { get; set; } = 8;
|
||||||
|
|
||||||
|
public TweetNotification.Size NotificationSize { get; set; } = TweetNotification.Size.Auto;
|
||||||
|
public Size CustomNotificationSize { get; set; } = Size.Empty;
|
||||||
|
public int NotificationScrollSpeed { get; set; } = 10;
|
||||||
|
|
||||||
|
private string _notificationSoundPath;
|
||||||
|
|
||||||
|
public string CustomCefArgs { get; set; } = null;
|
||||||
|
public string CustomBrowserCSS { get; set; } = null;
|
||||||
|
public string CustomNotificationCSS { get; set; } = null;
|
||||||
|
|
||||||
|
// SPECIAL PROPERTIES
|
||||||
|
|
||||||
|
public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
|
||||||
|
public bool IsCustomNotificationSizeSet => CustomNotificationSize != Size.Empty;
|
||||||
|
|
||||||
|
public TwitterUtils.ImageQuality TwitterImageQuality => BestImageQuality ? TwitterUtils.ImageQuality.Orig : TwitterUtils.ImageQuality.Default;
|
||||||
|
|
||||||
|
public string NotificationSoundPath{
|
||||||
|
get => string.IsNullOrEmpty(_notificationSoundPath) ? string.Empty : _notificationSoundPath;
|
||||||
|
set => _notificationSoundPath = value;
|
||||||
|
}
|
||||||
|
|
||||||
public bool MuteNotifications{
|
public bool MuteNotifications{
|
||||||
get{
|
get => _muteNotifications;
|
||||||
return muteNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (muteNotifications == value)return;
|
if (_muteNotifications != value){
|
||||||
|
_muteNotifications = value;
|
||||||
|
MuteToggled?.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
muteNotifications = value;
|
public int ZoomLevel{
|
||||||
|
get => _zoomLevel;
|
||||||
|
|
||||||
if (MuteToggled != null){
|
set{
|
||||||
MuteToggled(this, new EventArgs());
|
if (_zoomLevel != value){
|
||||||
|
_zoomLevel = value;
|
||||||
|
ZoomLevelChanged?.Invoke(this, new EventArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double ZoomMultiplier => _zoomLevel/100.0;
|
||||||
|
|
||||||
public TrayIcon.Behavior TrayBehavior{
|
public TrayIcon.Behavior TrayBehavior{
|
||||||
get{
|
get => _trayBehavior;
|
||||||
return trayBehavior;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (trayBehavior == value)return;
|
if (_trayBehavior != value){
|
||||||
|
_trayBehavior = value;
|
||||||
trayBehavior = value;
|
TrayBehaviorChanged?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
if (TrayBehaviorChanged != null){
|
|
||||||
TrayBehaviorChanged(this, new EventArgs());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// END OF CONFIGURATION
|
// EVENTS
|
||||||
|
|
||||||
[field:NonSerialized]
|
|
||||||
public event EventHandler MuteToggled;
|
public event EventHandler MuteToggled;
|
||||||
|
public event EventHandler ZoomLevelChanged;
|
||||||
[field:NonSerialized]
|
|
||||||
public event EventHandler TrayBehaviorChanged;
|
public event EventHandler TrayBehaviorChanged;
|
||||||
|
|
||||||
[NonSerialized]
|
// END OF CONFIG
|
||||||
private string file;
|
|
||||||
|
|
||||||
private int fileVersion;
|
private readonly string file;
|
||||||
private bool muteNotifications;
|
|
||||||
private TrayIcon.Behavior trayBehavior;
|
|
||||||
|
|
||||||
private UserConfig(string file){
|
public UserConfig(string file){ // TODO make private after removing UserConfigLegacy
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
BrowserWindow = new WindowState();
|
|
||||||
DisplayNotificationTimer = true;
|
|
||||||
NotificationDuration = TweetNotification.Duration.Medium;
|
|
||||||
NotificationPosition = TweetNotification.Position.TopRight;
|
|
||||||
CustomNotificationPosition = new Point(-32000, -32000);
|
|
||||||
NotificationEdgeDistance = 8;
|
|
||||||
NotificationDurationValue = 25;
|
|
||||||
EnableUpdateCheck = true;
|
|
||||||
ExpandLinksOnHover = true;
|
|
||||||
EnableTrayHighlight = true;
|
|
||||||
Plugins = new PluginConfig();
|
|
||||||
PluginsWindow = new WindowState();
|
|
||||||
|
|
||||||
Plugins.DisableOfficialFromConfig("clear-columns");
|
|
||||||
Plugins.DisableOfficialFromConfig("reply-account");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpgradeFile(){
|
|
||||||
if (fileVersion == CurrentFileVersion){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if outdated, cycle through all versions
|
|
||||||
if (fileVersion == 0){
|
|
||||||
DisplayNotificationTimer = true;
|
|
||||||
EnableUpdateCheck = true;
|
|
||||||
++fileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileVersion == 1){
|
|
||||||
ExpandLinksOnHover = true;
|
|
||||||
++fileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileVersion == 2){
|
|
||||||
BrowserWindow = new WindowState();
|
|
||||||
Plugins = new PluginConfig();
|
|
||||||
PluginsWindow = new WindowState();
|
|
||||||
++fileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileVersion == 3){
|
|
||||||
EnableTrayHighlight = true;
|
|
||||||
|
|
||||||
switch(NotificationDuration){
|
|
||||||
case TweetNotification.Duration.Short: NotificationDurationValue = 15; break;
|
|
||||||
case TweetNotification.Duration.Medium: NotificationDurationValue = 25; break;
|
|
||||||
case TweetNotification.Duration.Long: NotificationDurationValue = 35; break;
|
|
||||||
case TweetNotification.Duration.VeryLong: NotificationDurationValue = 45; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++fileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileVersion == 4){
|
|
||||||
Plugins.DisableOfficialFromConfig("clear-columns");
|
|
||||||
Plugins.DisableOfficialFromConfig("reply-account");
|
|
||||||
++fileVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the version
|
|
||||||
fileVersion = CurrentFileVersion;
|
|
||||||
Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Save(){
|
public bool Save(){
|
||||||
try{
|
try{
|
||||||
string directory = Path.GetDirectoryName(file);
|
WindowsUtils.CreateDirectoryForFile(file);
|
||||||
if (directory == null)return false;
|
|
||||||
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
|
|
||||||
if (File.Exists(file)){
|
if (File.Exists(file)){
|
||||||
string backupFile = GetBackupFile(file);
|
string backupFile = GetBackupFile(file);
|
||||||
@@ -183,10 +167,7 @@ namespace TweetDck.Configuration{
|
|||||||
File.Move(file, backupFile);
|
File.Move(file, backupFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
using(Stream stream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)){
|
Serializer.Write(file, this);
|
||||||
Formatter.Serialize(stream, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Program.Reporter.HandleException("Configuration Error", "Could not save the configuration file.", true, e);
|
Program.Reporter.HandleException("Configuration Error", "Could not save the configuration file.", true, e);
|
||||||
@@ -195,53 +176,40 @@ namespace TweetDck.Configuration{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static UserConfig Load(string file){
|
public static UserConfig Load(string file){
|
||||||
UserConfig config = null;
|
|
||||||
Exception firstException = null;
|
Exception firstException = null;
|
||||||
|
|
||||||
for(int attempt = 0; attempt < 2; attempt++){
|
for(int attempt = 0; attempt < 2; attempt++){
|
||||||
try{
|
try{
|
||||||
using(Stream stream = new FileStream(attempt == 0 ? file : GetBackupFile(file), FileMode.Open, FileAccess.Read, FileShare.Read)){
|
UserConfig config = new UserConfig(file);
|
||||||
if ((config = Formatter.Deserialize(stream) as UserConfig) != null){
|
Serializer.Read(attempt == 0 ? file : GetBackupFile(file), config);
|
||||||
config.file = file;
|
return config;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config != null){
|
|
||||||
config.UpgradeFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}catch(FileNotFoundException){
|
}catch(FileNotFoundException){
|
||||||
}catch(DirectoryNotFoundException){
|
}catch(DirectoryNotFoundException){
|
||||||
break;
|
break;
|
||||||
|
}catch(FormatException){
|
||||||
|
UserConfig config = UserConfigLegacy.Load(file);
|
||||||
|
config.Save();
|
||||||
|
return config;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
if (attempt == 0){
|
if (attempt == 0){
|
||||||
firstException = e;
|
firstException = e;
|
||||||
Program.Reporter.Log(e.ToString());
|
Program.Reporter.Log(e.ToString());
|
||||||
}
|
}
|
||||||
else if (firstException != null){
|
else if (firstException != null){
|
||||||
Program.Reporter.HandleException("Configuration Error", "Could not open the backup configuration file. If you continue, you may lose your settings and list of enabled plugins.", true, e);
|
Program.Reporter.HandleException("Configuration Error", "Could not open the backup configuration file. If you continue, your program options will be reset.", true, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstException != null && config == null){
|
if (firstException != null){
|
||||||
Program.Reporter.HandleException("Configuration Error", "Could not open the configuration file.", true, firstException);
|
Program.Reporter.HandleException("Configuration Error", "Could not open the configuration file.", true, firstException);
|
||||||
}
|
}
|
||||||
|
|
||||||
return config ?? new UserConfig(file);
|
return new UserConfig(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetBackupFile(string file){
|
public static string GetBackupFile(string file){
|
||||||
return file+".bak";
|
return file+".bak";
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SerializationCompatibilityHandler : SerializationBinder{
|
|
||||||
public override Type BindToType(string assemblyName, string typeName){
|
|
||||||
assemblyName = assemblyName.Replace("TweetDick", "TweetDuck");
|
|
||||||
typeName = typeName.Replace("TweetDick", "TweetDck");
|
|
||||||
return Type.GetType(string.Format(CultureInfo.CurrentCulture, "{0}, {1}", typeName, assemblyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
210
Configuration/UserConfigLegacy.cs
Normal file
210
Configuration/UserConfigLegacy.cs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
using TweetDuck.Core;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Notification;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
|
||||||
|
namespace TweetDuck.Configuration{
|
||||||
|
[Serializable]
|
||||||
|
sealed class UserConfigLegacy{ // TODO remove eventually
|
||||||
|
private static readonly IFormatter Formatter = new BinaryFormatter{ Binder = new LegacyBinder() };
|
||||||
|
|
||||||
|
private class LegacyBinder : SerializationBinder{
|
||||||
|
public override Type BindToType(string assemblyName, string typeName){
|
||||||
|
return Type.GetType(string.Format("{0}, {1}", typeName.Replace("TweetDck", "TweetDuck").Replace(".UserConfig", ".UserConfigLegacy").Replace("Core.Utils.WindowState", "Data.WindowState"), assemblyName.Replace("TweetDck", "TweetDuck")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int CurrentFileVersion = 11;
|
||||||
|
|
||||||
|
// START OF CONFIGURATION
|
||||||
|
|
||||||
|
public WindowState BrowserWindow { get; set; }
|
||||||
|
public WindowState PluginsWindow { get; set; }
|
||||||
|
|
||||||
|
public bool DisplayNotificationColumn { get; set; }
|
||||||
|
public bool DisplayNotificationTimer { get; set; }
|
||||||
|
public bool NotificationTimerCountDown { get; set; }
|
||||||
|
public bool NotificationSkipOnLinkClick { get; set; }
|
||||||
|
public bool NotificationNonIntrusiveMode { get; set; }
|
||||||
|
|
||||||
|
public int NotificationIdlePauseSeconds { get; set; }
|
||||||
|
public int NotificationDurationValue { get; set; }
|
||||||
|
public int NotificationScrollSpeed { get; set; }
|
||||||
|
|
||||||
|
public TweetNotification.Position NotificationPosition { get; set; }
|
||||||
|
public Point CustomNotificationPosition { get; set; }
|
||||||
|
public int NotificationEdgeDistance { get; set; }
|
||||||
|
public int NotificationDisplay { get; set; }
|
||||||
|
|
||||||
|
public TweetNotification.Size NotificationSize { get; set; }
|
||||||
|
public Size CustomNotificationSize { get; set; }
|
||||||
|
|
||||||
|
public bool EnableSpellCheck { get; set; }
|
||||||
|
public bool ExpandLinksOnHover { get; set; }
|
||||||
|
public bool SwitchAccountSelectors { get; set; }
|
||||||
|
public bool EnableTrayHighlight { get; set; }
|
||||||
|
|
||||||
|
public bool EnableUpdateCheck { get; set; }
|
||||||
|
public string DismissedUpdate { get; set; }
|
||||||
|
|
||||||
|
public string CustomCefArgs { get; set; }
|
||||||
|
public string CustomBrowserCSS { get; set; }
|
||||||
|
public string CustomNotificationCSS { get; set; }
|
||||||
|
|
||||||
|
public string NotificationSoundPath{
|
||||||
|
get => string.IsNullOrEmpty(notificationSoundPath) ? string.Empty : notificationSoundPath;
|
||||||
|
set => notificationSoundPath = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MuteNotifications{
|
||||||
|
get => muteNotifications;
|
||||||
|
set => muteNotifications = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ZoomLevel{
|
||||||
|
get => zoomLevel;
|
||||||
|
set => zoomLevel = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrayIcon.Behavior TrayBehavior{
|
||||||
|
get => trayBehavior;
|
||||||
|
set => trayBehavior = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// END OF CONFIGURATION
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
private string file;
|
||||||
|
|
||||||
|
private int fileVersion;
|
||||||
|
private bool muteNotifications;
|
||||||
|
private int zoomLevel;
|
||||||
|
private string notificationSoundPath;
|
||||||
|
private TrayIcon.Behavior trayBehavior;
|
||||||
|
|
||||||
|
private UserConfigLegacy(string file){
|
||||||
|
this.file = file;
|
||||||
|
|
||||||
|
BrowserWindow = new WindowState();
|
||||||
|
ZoomLevel = 100;
|
||||||
|
DisplayNotificationTimer = true;
|
||||||
|
NotificationNonIntrusiveMode = true;
|
||||||
|
NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
|
CustomNotificationPosition = ControlExtensions.InvisibleLocation;
|
||||||
|
NotificationSize = TweetNotification.Size.Auto;
|
||||||
|
NotificationEdgeDistance = 8;
|
||||||
|
NotificationDurationValue = 25;
|
||||||
|
NotificationScrollSpeed = 100;
|
||||||
|
EnableUpdateCheck = true;
|
||||||
|
ExpandLinksOnHover = true;
|
||||||
|
SwitchAccountSelectors = true;
|
||||||
|
EnableTrayHighlight = true;
|
||||||
|
PluginsWindow = new WindowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeFile(){
|
||||||
|
if (fileVersion == CurrentFileVersion){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if outdated, cycle through all versions
|
||||||
|
if (fileVersion <= 5){
|
||||||
|
DisplayNotificationTimer = true;
|
||||||
|
EnableUpdateCheck = true;
|
||||||
|
ExpandLinksOnHover = true;
|
||||||
|
BrowserWindow = new WindowState();
|
||||||
|
PluginsWindow = new WindowState();
|
||||||
|
EnableTrayHighlight = true;
|
||||||
|
NotificationDurationValue = 25;
|
||||||
|
fileVersion = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 6){
|
||||||
|
NotificationNonIntrusiveMode = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 7){
|
||||||
|
ZoomLevel = 100;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 8){
|
||||||
|
SwitchAccountSelectors = true;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 9){
|
||||||
|
NotificationScrollSpeed = 100;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileVersion == 10){
|
||||||
|
NotificationSize = TweetNotification.Size.Auto;
|
||||||
|
++fileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the version
|
||||||
|
fileVersion = CurrentFileVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserConfig ConvertLegacy(){
|
||||||
|
return new UserConfig(file){
|
||||||
|
BrowserWindow = BrowserWindow,
|
||||||
|
PluginsWindow = PluginsWindow,
|
||||||
|
DisplayNotificationColumn = DisplayNotificationColumn,
|
||||||
|
DisplayNotificationTimer = DisplayNotificationTimer,
|
||||||
|
NotificationTimerCountDown = NotificationTimerCountDown,
|
||||||
|
NotificationSkipOnLinkClick = NotificationSkipOnLinkClick,
|
||||||
|
NotificationNonIntrusiveMode = NotificationNonIntrusiveMode,
|
||||||
|
NotificationIdlePauseSeconds = NotificationIdlePauseSeconds,
|
||||||
|
NotificationDurationValue = NotificationDurationValue,
|
||||||
|
NotificationScrollSpeed = NotificationScrollSpeed,
|
||||||
|
NotificationPosition = NotificationPosition,
|
||||||
|
CustomNotificationPosition = CustomNotificationPosition,
|
||||||
|
NotificationEdgeDistance = NotificationEdgeDistance,
|
||||||
|
NotificationDisplay = NotificationDisplay,
|
||||||
|
NotificationSize = NotificationSize,
|
||||||
|
CustomNotificationSize = CustomNotificationSize,
|
||||||
|
EnableSpellCheck = EnableSpellCheck,
|
||||||
|
ExpandLinksOnHover = ExpandLinksOnHover,
|
||||||
|
SwitchAccountSelectors = SwitchAccountSelectors,
|
||||||
|
EnableTrayHighlight = EnableTrayHighlight,
|
||||||
|
EnableUpdateCheck = EnableUpdateCheck,
|
||||||
|
DismissedUpdate = DismissedUpdate,
|
||||||
|
CustomCefArgs = CustomCefArgs,
|
||||||
|
CustomBrowserCSS = CustomBrowserCSS,
|
||||||
|
CustomNotificationCSS = CustomNotificationCSS,
|
||||||
|
NotificationSoundPath = NotificationSoundPath,
|
||||||
|
MuteNotifications = MuteNotifications,
|
||||||
|
ZoomLevel = ZoomLevel,
|
||||||
|
TrayBehavior = TrayBehavior
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UserConfig Load(string file){
|
||||||
|
UserConfigLegacy config = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
using(Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)){
|
||||||
|
if ((config = Formatter.Deserialize(stream) as UserConfigLegacy) != null){
|
||||||
|
config.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config?.UpgradeFile();
|
||||||
|
}catch(FileNotFoundException){
|
||||||
|
}catch(DirectoryNotFoundException){
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Configuration Error", "Could not open the configuration file.", true, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (config ?? new UserConfigLegacy(file)).ConvertLegacy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
|
||||||
<package id="cef.redist.x64" version="3.2785.1478" targetFramework="net452" />
|
|
||||||
<package id="cef.redist.x86" version="3.2785.1478" targetFramework="net452" />
|
|
||||||
<package id="CefSharp.Common" version="53.0.0-pre01" targetFramework="net452" />
|
|
||||||
<package id="CefSharp.WinForms" version="53.0.0-pre01" targetFramework="net452" />
|
|
||||||
<package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net452" />
|
|
||||||
</packages>
|
|
||||||
19
Core/Bridge/CallbackBridge.cs
Normal file
19
Core/Bridge/CallbackBridge.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Bridge{
|
||||||
|
sealed class CallbackBridge{
|
||||||
|
private readonly Control owner;
|
||||||
|
private readonly Action safeCallback;
|
||||||
|
|
||||||
|
public CallbackBridge(Control owner, Action safeCallback){
|
||||||
|
this.owner = owner;
|
||||||
|
this.safeCallback = safeCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trigger(){
|
||||||
|
owner.InvokeSafe(safeCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Core/Bridge/PropertyBridge.cs
Normal file
32
Core/Bridge/PropertyBridge.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Bridge{
|
||||||
|
static class PropertyBridge{
|
||||||
|
public enum Environment{
|
||||||
|
Browser, Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateScript(Environment environment){
|
||||||
|
string Bool(bool value){
|
||||||
|
return value ? "true;" : "false;";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder build = new StringBuilder().Append("(function(x){");
|
||||||
|
|
||||||
|
build.Append("x.expandLinksOnHover=").Append(Bool(Program.UserConfig.ExpandLinksOnHover));
|
||||||
|
|
||||||
|
if (environment == Environment.Browser){
|
||||||
|
build.Append("x.switchAccountSelectors=").Append(Bool(Program.UserConfig.SwitchAccountSelectors));
|
||||||
|
build.Append("x.muteNotifications=").Append(Bool(Program.UserConfig.MuteNotifications));
|
||||||
|
build.Append("x.hasCustomNotificationSound=").Append(Bool(Program.UserConfig.NotificationSoundPath.Length > 0));
|
||||||
|
build.Append("x.notificationMediaPreviews=").Append(Bool(Program.UserConfig.NotificationMediaPreviews));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environment == Environment.Notification){
|
||||||
|
build.Append("x.skipOnLinkClick=").Append(Bool(Program.UserConfig.NotificationSkipOnLinkClick));
|
||||||
|
}
|
||||||
|
|
||||||
|
return build.Append("})(window.$TDX=window.$TDX||{})").ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
157
Core/Bridge/TweetDeckBridge.cs
Normal file
157
Core/Bridge/TweetDeckBridge.cs
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Notification;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Bridge{
|
||||||
|
sealed class TweetDeckBridge{
|
||||||
|
public static string LastRightClickedLink = string.Empty;
|
||||||
|
public static string LastRightClickedImage = string.Empty;
|
||||||
|
public static string LastHighlightedTweet = string.Empty;
|
||||||
|
public static string LastHighlightedQuotedTweet = string.Empty;
|
||||||
|
public static string LastHighlightedTweetAuthor = string.Empty;
|
||||||
|
public static string[] LastHighlightedTweetImages = StringUtils.EmptyArray;
|
||||||
|
public static Dictionary<string, string> SessionData = new Dictionary<string, string>(2);
|
||||||
|
|
||||||
|
public static void ResetStaticProperties(){
|
||||||
|
LastRightClickedLink = LastRightClickedImage = LastHighlightedTweet = LastHighlightedQuotedTweet = LastHighlightedTweetAuthor = string.Empty;
|
||||||
|
LastHighlightedTweetImages = StringUtils.EmptyArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RestoreSessionData(IFrame frame){
|
||||||
|
if (SessionData.Count > 0){
|
||||||
|
StringBuilder build = new StringBuilder().Append("window.TD_SESSION={");
|
||||||
|
|
||||||
|
foreach(KeyValuePair<string, string> kvp in SessionData){
|
||||||
|
build.Append(kvp.Key).Append(":'").Append(kvp.Value.Replace("'", "\\'")).Append("',");
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLoader.ExecuteScript(frame, build.Append("}").ToString(), "gen:session");
|
||||||
|
SessionData.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly FormBrowser form;
|
||||||
|
private readonly FormNotificationMain notification;
|
||||||
|
|
||||||
|
public TweetDeckBridge(FormBrowser form, FormNotificationMain notification){
|
||||||
|
this.form = form;
|
||||||
|
this.notification = notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadFontSizeClass(string fsClass){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
TweetNotification.SetFontSizeClass(fsClass);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNotificationHeadContents(string headContents){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
TweetNotification.SetHeadTag(headContents);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastRightClickedLink(string link){
|
||||||
|
form.InvokeAsyncSafe(() => LastRightClickedLink = link);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastRightClickedImage(string link){
|
||||||
|
form.InvokeAsyncSafe(() => LastRightClickedImage = link);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLastHighlightedTweet(string link, string quotedLink, string author, string imageList){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
LastHighlightedTweet = link;
|
||||||
|
LastHighlightedQuotedTweet = quotedLink;
|
||||||
|
LastHighlightedTweetAuthor = author;
|
||||||
|
LastHighlightedTweetImages = imageList.Split(';');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenContextMenu(){
|
||||||
|
form.InvokeAsyncSafe(form.OpenContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetPopup(string columnName, string tweetHtml, int tweetCharacters, string tweetUrl, string quoteUrl){
|
||||||
|
notification.InvokeAsyncSafe(() => {
|
||||||
|
form.OnTweetNotification();
|
||||||
|
notification.ShowNotification(new TweetNotification(columnName, tweetHtml, tweetCharacters, tweetUrl, quoteUrl));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetSound(){
|
||||||
|
form.InvokeAsyncSafe(() => {
|
||||||
|
form.OnTweetNotification();
|
||||||
|
form.PlayNotificationSound();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayTooltip(string text, bool showInNotification){
|
||||||
|
if (showInNotification){
|
||||||
|
notification.InvokeAsyncSafe(() => notification.DisplayTooltip(text));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
form.InvokeAsyncSafe(() => form.DisplayTooltip(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSessionData(string key, string value){
|
||||||
|
form.InvokeSafe(() => { // do not use InvokeAsyncSafe, return only after invocation
|
||||||
|
SessionData.Add(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNextNotification(){
|
||||||
|
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ScreenshotTweet(string html, int width, int height){
|
||||||
|
form.InvokeAsyncSafe(() => form.OnTweetScreenshotReady(html, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayVideo(string url){
|
||||||
|
form.InvokeAsyncSafe(() => form.PlayVideo(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FixClipboard(){
|
||||||
|
form.InvokeAsyncSafe(WindowsUtils.ClipboardStripHtmlStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetIdleSeconds(){
|
||||||
|
return NativeMethods.GetIdleSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenBrowser(string url){
|
||||||
|
BrowserUtils.OpenExternalBrowser(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Alert(string type, string contents){
|
||||||
|
MessageBoxIcon icon;
|
||||||
|
|
||||||
|
switch(type){
|
||||||
|
case "error": icon = MessageBoxIcon.Error; break;
|
||||||
|
case "warning": icon = MessageBoxIcon.Warning; break;
|
||||||
|
case "info": icon = MessageBoxIcon.Information; break;
|
||||||
|
default: icon = MessageBoxIcon.None; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FormMessage.Show("TweetDuck Browser Message", contents, icon, FormMessage.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CrashDebug(string message){
|
||||||
|
#if DEBUG
|
||||||
|
Log(message);
|
||||||
|
System.Diagnostics.Debugger.Break();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(string data){
|
||||||
|
System.Diagnostics.Debug.WriteLine(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetLib.Communication;
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
namespace TweetDuck.Core.Controls{
|
||||||
static class ControlExtensions{
|
static class ControlExtensions{
|
||||||
|
public static readonly Point InvisibleLocation = new Point(-32000, -32000);
|
||||||
|
|
||||||
public static void InvokeSafe(this Control control, Action func){
|
public static void InvokeSafe(this Control control, Action func){
|
||||||
if (control.InvokeRequired){
|
if (control.InvokeRequired){
|
||||||
control.Invoke(func);
|
control.Invoke(func);
|
||||||
@@ -13,6 +18,20 @@ namespace TweetDck.Core.Controls{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void InvokeAsyncSafe(this Control control, Action func){
|
||||||
|
control.BeginInvoke(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float GetDPIScale(this Control control){
|
||||||
|
using(Graphics graphics = control.CreateGraphics()){
|
||||||
|
return graphics.DpiY/96F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsFullyOutsideView(this Form form){
|
||||||
|
return !Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(form.Bounds));
|
||||||
|
}
|
||||||
|
|
||||||
public static void MoveToCenter(this Form targetForm, Form parentForm){
|
public static void MoveToCenter(this Form targetForm, Form parentForm){
|
||||||
targetForm.Location = new Point(parentForm.Location.X+parentForm.Width/2-targetForm.Width/2, parentForm.Location.Y+parentForm.Height/2-targetForm.Height/2);
|
targetForm.Location = new Point(parentForm.Location.X+parentForm.Width/2-targetForm.Width/2, parentForm.Location.Y+parentForm.Height/2-targetForm.Height/2);
|
||||||
}
|
}
|
||||||
@@ -29,12 +48,32 @@ namespace TweetDck.Core.Controls{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetValueSafe(this NumericUpDown numUpDown, int value){
|
||||||
|
if (value >= numUpDown.Minimum && value <= numUpDown.Maximum){
|
||||||
|
numUpDown.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetValueSafe(this TrackBar trackBar, int value){
|
public static void SetValueSafe(this TrackBar trackBar, int value){
|
||||||
if (value >= trackBar.Minimum && value <= trackBar.Maximum){
|
if (value >= trackBar.Minimum && value <= trackBar.Maximum){
|
||||||
trackBar.Value = value;
|
trackBar.Value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool AlignValueToTick(this TrackBar trackBar){
|
||||||
|
if (trackBar.Value % trackBar.SmallChange != 0){
|
||||||
|
trackBar.Value = trackBar.SmallChange*(int)Math.Floor(((double)trackBar.Value/trackBar.SmallChange)+0.5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetElevated(this Button button){
|
||||||
|
button.Text = " "+button.Text;
|
||||||
|
button.FlatStyle = FlatStyle.System;
|
||||||
|
Comms.SendMessage(button.Handle, NativeMethods.BCM_SETSHIELD, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
public static void EnableMultilineShortcuts(this TextBox textBox){
|
public static void EnableMultilineShortcuts(this TextBox textBox){
|
||||||
textBox.KeyDown += (sender, args) => {
|
textBox.KeyDown += (sender, args) => {
|
||||||
if (args.Control && args.KeyCode == Keys.A){
|
if (args.Control && args.KeyCode == Keys.A){
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
namespace TweetDuck.Core.Controls{
|
||||||
class FlatButton : Button{
|
class FlatButton : Button{
|
||||||
protected override bool ShowFocusCues{
|
protected override bool ShowFocusCues => false;
|
||||||
get{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlatButton(){
|
public FlatButton(){
|
||||||
GotFocus += FlatButton_GotFocus;
|
GotFocus += FlatButton_GotFocus;
|
||||||
|
|||||||
3
Core/Controls/FlatProgressBar.Designer.cs
generated
3
Core/Controls/FlatProgressBar.Designer.cs
generated
@@ -1,3 +0,0 @@
|
|||||||
namespace TweetDck.Core.Controls{
|
|
||||||
partial class FlatProgressBar{}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
namespace TweetDuck.Core.Controls{
|
||||||
sealed partial class FlatProgressBar : ProgressBar{
|
sealed class FlatProgressBar : ProgressBar{
|
||||||
private readonly SolidBrush brush;
|
private readonly SolidBrush brush;
|
||||||
|
|
||||||
public FlatProgressBar(){
|
public FlatProgressBar(){
|
||||||
|
|||||||
23
Core/Controls/LabelVertical.cs
Normal file
23
Core/Controls/LabelVertical.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Controls{
|
||||||
|
sealed class LabelVertical : Label{
|
||||||
|
public int LineHeight { get; set; }
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e){
|
||||||
|
int y = (int)Math.Floor((ClientRectangle.Height-Text.Length*LineHeight)/2F)-2; // 2 = random
|
||||||
|
|
||||||
|
using(Brush brush = new SolidBrush(ForeColor)){
|
||||||
|
foreach(char chr in Text){
|
||||||
|
string str = chr.ToString();
|
||||||
|
float x = (ClientRectangle.Width-e.Graphics.MeasureString(str, Font).Width)/2F;
|
||||||
|
|
||||||
|
e.Graphics.DrawString(str, Font, brush, x, y);
|
||||||
|
y += LineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Core/Controls/NumericUpDownEx.cs
Normal file
18
Core/Controls/NumericUpDownEx.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Controls{
|
||||||
|
sealed class NumericUpDownEx : NumericUpDown{
|
||||||
|
public string TextSuffix { get; set ; }
|
||||||
|
|
||||||
|
protected override void UpdateEditText(){
|
||||||
|
base.UpdateEditText();
|
||||||
|
|
||||||
|
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime){
|
||||||
|
ChangingText = true;
|
||||||
|
Text += TextSuffix;
|
||||||
|
ChangingText = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Core/Controls/TabButton.Designer.cs
generated
3
Core/Controls/TabButton.Designer.cs
generated
@@ -1,3 +0,0 @@
|
|||||||
namespace TweetDck.Core.Controls{
|
|
||||||
partial class TabButton{}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
|
||||||
sealed partial class TabButton : FlatButton{
|
|
||||||
public Action Callback { get; private set; }
|
|
||||||
|
|
||||||
public void SetupButton(int locationX, int sizeWidth, string title, Action callback){
|
|
||||||
Callback = callback;
|
|
||||||
|
|
||||||
SuspendLayout();
|
|
||||||
FlatAppearance.BorderColor = Color.DimGray;
|
|
||||||
FlatAppearance.MouseDownBackColor = Color.White;
|
|
||||||
FlatAppearance.MouseOverBackColor = Color.White;
|
|
||||||
FlatStyle = FlatStyle.Flat;
|
|
||||||
Location = new Point(locationX, 0);
|
|
||||||
Margin = new Padding(0);
|
|
||||||
Size = new Size(sizeWidth, 30);
|
|
||||||
Text = title;
|
|
||||||
UseVisualStyleBackColor = true;
|
|
||||||
ResumeLayout(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
68
Core/Controls/TabPanel.Designer.cs
generated
68
Core/Controls/TabPanel.Designer.cs
generated
@@ -1,68 +0,0 @@
|
|||||||
namespace TweetDck.Core.Controls {
|
|
||||||
partial class TabPanel {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Component Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
this.panelButtons = new System.Windows.Forms.Panel();
|
|
||||||
this.panelContent = new System.Windows.Forms.Panel();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// panelButtons
|
|
||||||
//
|
|
||||||
this.panelButtons.Dock = System.Windows.Forms.DockStyle.Top;
|
|
||||||
this.panelButtons.Location = new System.Drawing.Point(0, 0);
|
|
||||||
this.panelButtons.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.panelButtons.Name = "panelButtons";
|
|
||||||
this.panelButtons.Size = new System.Drawing.Size(640, 30);
|
|
||||||
this.panelButtons.TabIndex = 0;
|
|
||||||
//
|
|
||||||
// panelContent
|
|
||||||
//
|
|
||||||
this.panelContent.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.panelContent.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
|
||||||
this.panelContent.Location = new System.Drawing.Point(0, 29);
|
|
||||||
this.panelContent.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.panelContent.Name = "panelContent";
|
|
||||||
this.panelContent.Size = new System.Drawing.Size(640, 451);
|
|
||||||
this.panelContent.TabIndex = 1;
|
|
||||||
//
|
|
||||||
// TabPanel
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.Controls.Add(this.panelContent);
|
|
||||||
this.Controls.Add(this.panelButtons);
|
|
||||||
this.Name = "TabPanel";
|
|
||||||
this.Size = new System.Drawing.Size(640, 480);
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.Panel panelButtons;
|
|
||||||
private System.Windows.Forms.Panel panelContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Controls{
|
|
||||||
sealed partial class TabPanel : UserControl{
|
|
||||||
public IEnumerable<TabButton> Buttons{
|
|
||||||
get{
|
|
||||||
return panelButtons.Controls.Cast<TabButton>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TabButton ActiveButton { get; private set; }
|
|
||||||
|
|
||||||
// ReSharper disable once ConvertToAutoPropertyWithPrivateSetter
|
|
||||||
public Panel Content{
|
|
||||||
get{
|
|
||||||
return panelContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int btnWidth;
|
|
||||||
|
|
||||||
public TabPanel(){
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetupTabPanel(int buttonWidth){
|
|
||||||
this.btnWidth = buttonWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TabButton AddButton(string title, Action callback){
|
|
||||||
TabButton button = new TabButton();
|
|
||||||
button.SetupButton((btnWidth-1)*panelButtons.Controls.Count, btnWidth, title, callback);
|
|
||||||
button.Click += (sender, args) => SelectTab((TabButton)sender);
|
|
||||||
|
|
||||||
panelButtons.Controls.Add(button);
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SelectTab(TabButton button){
|
|
||||||
if (ActiveButton != null){
|
|
||||||
ActiveButton.BackColor = SystemColors.Control;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.BackColor = Color.White;
|
|
||||||
button.Callback();
|
|
||||||
|
|
||||||
ActiveButton = button;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReplaceContent(Control newControl){
|
|
||||||
newControl.Dock = DockStyle.Fill;
|
|
||||||
Content.SuspendLayout();
|
|
||||||
Content.Controls.Clear();
|
|
||||||
Content.Controls.Add(newControl);
|
|
||||||
Content.ResumeLayout(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
16
Core/FormBrowser.Designer.cs
generated
16
Core/FormBrowser.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core {
|
namespace TweetDuck.Core {
|
||||||
sealed partial class FormBrowser {
|
sealed partial class FormBrowser {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -24,26 +24,31 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.trayIcon = new TweetDck.Core.TrayIcon();
|
this.trayIcon = new TweetDuck.Core.TrayIcon(this.components);
|
||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.timerResize = new System.Windows.Forms.Timer(this.components);
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// trayIcon
|
// timerResize
|
||||||
//
|
//
|
||||||
this.trayIcon.Visible = false;
|
this.timerResize.Interval = 500;
|
||||||
|
this.timerResize.Tick += new System.EventHandler(this.timerResize_Tick);
|
||||||
//
|
//
|
||||||
// FormBrowser
|
// FormBrowser
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.BackColor = TweetDuck.Core.Utils.TwitterUtils.BackgroundColor;
|
||||||
this.ClientSize = new System.Drawing.Size(324, 386);
|
this.ClientSize = new System.Drawing.Size(324, 386);
|
||||||
this.Icon = Properties.Resources.icon;
|
this.Icon = Properties.Resources.icon;
|
||||||
this.Location = new System.Drawing.Point(-32000, -32000);
|
this.Location = TweetDuck.Core.Controls.ControlExtensions.InvisibleLocation;
|
||||||
this.MinimumSize = new System.Drawing.Size(340, 424);
|
this.MinimumSize = new System.Drawing.Size(340, 424);
|
||||||
this.Name = "FormBrowser";
|
this.Name = "FormBrowser";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
|
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
|
||||||
|
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
|
||||||
|
this.LocationChanged += new System.EventHandler(this.FormBrowser_LocationChanged);
|
||||||
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
|
||||||
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
this.Resize += new System.EventHandler(this.FormBrowser_Resize);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
@@ -54,6 +59,7 @@
|
|||||||
|
|
||||||
private TrayIcon trayIcon;
|
private TrayIcon trayIcon;
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.Timer timerResize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,45 @@
|
|||||||
using System;
|
using CefSharp;
|
||||||
using System.Windows.Forms;
|
|
||||||
using CefSharp;
|
|
||||||
using CefSharp.WinForms;
|
using CefSharp.WinForms;
|
||||||
using TweetDck.Configuration;
|
using System;
|
||||||
using TweetDck.Core.Handling;
|
|
||||||
using TweetDck.Core.Other;
|
|
||||||
using TweetDck.Resources;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using TweetDck.Updates;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Plugins;
|
using TweetDuck.Configuration;
|
||||||
using TweetDck.Plugins.Events;
|
using TweetDuck.Core.Bridge;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Handling;
|
||||||
|
using TweetDuck.Core.Handling.General;
|
||||||
|
using TweetDuck.Core.Notification;
|
||||||
|
using TweetDuck.Core.Notification.Screenshot;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
using TweetDuck.Core.Other.Management;
|
||||||
|
using TweetDuck.Core.Other.Settings;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using TweetDuck.Plugins.Enums;
|
||||||
|
using TweetDuck.Plugins.Events;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
using TweetDuck.Updates;
|
||||||
|
using TweetDuck.Updates.Events;
|
||||||
|
using TweetLib.Audio;
|
||||||
|
|
||||||
namespace TweetDck.Core{
|
namespace TweetDuck.Core{
|
||||||
sealed partial class FormBrowser : Form{
|
sealed partial class FormBrowser : Form{
|
||||||
private static UserConfig Config{
|
private static UserConfig Config => Program.UserConfig;
|
||||||
get{
|
|
||||||
return Program.UserConfig;
|
public bool IsWaiting{
|
||||||
|
set{
|
||||||
|
if (value){
|
||||||
|
browser.Enabled = false;
|
||||||
|
Cursor = Cursors.WaitCursor;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
browser.Enabled = true;
|
||||||
|
Cursor = Cursors.Default;
|
||||||
|
|
||||||
|
if (Focused){ // re-focus browser only if the window or a child is activated
|
||||||
|
browser.Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,41 +48,78 @@ namespace TweetDck.Core{
|
|||||||
private readonly ChromiumWebBrowser browser;
|
private readonly ChromiumWebBrowser browser;
|
||||||
private readonly PluginManager plugins;
|
private readonly PluginManager plugins;
|
||||||
private readonly UpdateHandler updates;
|
private readonly UpdateHandler updates;
|
||||||
|
private readonly FormNotificationTweet notification;
|
||||||
|
private readonly ContextMenu contextMenu;
|
||||||
|
private readonly MemoryUsageTracker memoryUsageTracker;
|
||||||
|
|
||||||
private FormSettings currentFormSettings;
|
|
||||||
private FormAbout currentFormAbout;
|
|
||||||
private FormPlugins currentFormPlugins;
|
|
||||||
private bool isLoaded;
|
private bool isLoaded;
|
||||||
|
private bool isBrowserReady;
|
||||||
private FormWindowState prevState;
|
private FormWindowState prevState;
|
||||||
|
|
||||||
public FormBrowser(PluginManager pluginManager){
|
private TweetScreenshotManager notificationScreenshotManager;
|
||||||
|
private SoundNotification soundNotification;
|
||||||
|
private VideoPlayer videoPlayer;
|
||||||
|
|
||||||
|
public FormBrowser(UpdaterSettings updaterSettings){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName;
|
Text = Program.BrandName;
|
||||||
|
|
||||||
this.plugins = pluginManager;
|
this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath);
|
||||||
this.plugins.Reloaded += plugins_Reloaded;
|
this.plugins.Reloaded += plugins_Reloaded;
|
||||||
this.plugins.Config.PluginChangedState += plugins_PluginChangedState;
|
this.plugins.Executed += plugins_Executed;
|
||||||
|
this.plugins.PluginChangedState += plugins_PluginChangedState;
|
||||||
|
this.plugins.Reload();
|
||||||
|
|
||||||
FormNotification notification = CreateNotificationForm(true);
|
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
||||||
notification.CanMoveWindow = () => false;
|
this.memoryUsageTracker = new MemoryUsageTracker("TDGF_tryRunCleanup");
|
||||||
notification.Show();
|
|
||||||
|
this.notification = new FormNotificationTweet(this, plugins){
|
||||||
|
#if DEBUG
|
||||||
|
CanMoveWindow = () => (ModifierKeys & Keys.Alt) == Keys.Alt
|
||||||
|
#else
|
||||||
|
CanMoveWindow = () => false
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notification.Show();
|
||||||
|
|
||||||
this.browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){
|
this.browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){
|
||||||
MenuHandler = new ContextMenuBrowser(this),
|
MenuHandler = new ContextMenuBrowser(this),
|
||||||
DialogHandler = new DialogHandlerBrowser(this),
|
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||||
LifeSpanHandler = new LifeSpanHandler()
|
KeyboardHandler = new KeyboardHandlerBrowser(this),
|
||||||
|
LifeSpanHandler = new LifeSpanHandler(),
|
||||||
|
RequestHandler = new RequestHandlerBrowser()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
#if DEBUG
|
||||||
this.browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
this.browser.ConsoleMessage += BrowserUtils.HandleConsoleMessage;
|
||||||
this.browser.RegisterJsObject("$TD", new TweetDeckBridge(this, notification));
|
#endif
|
||||||
|
|
||||||
|
this.browser.LoadingStateChanged += browser_LoadingStateChanged;
|
||||||
|
this.browser.FrameLoadStart += browser_FrameLoadStart;
|
||||||
|
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
||||||
|
this.browser.LoadError += browser_LoadError;
|
||||||
|
this.browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge(this, notification));
|
||||||
this.browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
this.browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
||||||
|
|
||||||
|
browser.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb();
|
||||||
|
browser.Dock = DockStyle.None;
|
||||||
|
browser.Location = ControlExtensions.InvisibleLocation;
|
||||||
Controls.Add(browser);
|
Controls.Add(browser);
|
||||||
|
|
||||||
Disposed += (sender, args) => browser.Dispose();
|
Controls.Add(new MenuStrip{ Visible = false }); // fixes Alt freezing the program in Win 10 Anniversary Update
|
||||||
|
|
||||||
|
Disposed += (sender, args) => {
|
||||||
|
memoryUsageTracker.Dispose();
|
||||||
|
|
||||||
|
browser.Dispose();
|
||||||
|
contextMenu.Dispose();
|
||||||
|
|
||||||
|
notificationScreenshotManager?.Dispose();
|
||||||
|
soundNotification?.Dispose();
|
||||||
|
videoPlayer?.Dispose();
|
||||||
|
};
|
||||||
|
|
||||||
this.trayIcon.ClickRestore += trayIcon_ClickRestore;
|
this.trayIcon.ClickRestore += trayIcon_ClickRestore;
|
||||||
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
this.trayIcon.ClickClose += trayIcon_ClickClose;
|
||||||
@@ -67,67 +127,124 @@ namespace TweetDck.Core{
|
|||||||
|
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
|
|
||||||
this.updates = new UpdateHandler(browser, this);
|
Config.MuteToggled += Config_MuteToggled;
|
||||||
|
Config.ZoomLevelChanged += Config_ZoomLevelChanged;
|
||||||
|
|
||||||
|
this.updates = new UpdateHandler(browser, updaterSettings);
|
||||||
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
||||||
|
this.updates.UpdateDismissed += updates_UpdateDismissed;
|
||||||
|
|
||||||
|
RestoreWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowChildForm(Form form){
|
private void ShowChildForm(Form form){
|
||||||
|
form.VisibleChanged += (sender, args) => form.MoveToCenter(this);
|
||||||
form.Show(this);
|
form.Show(this);
|
||||||
form.Shown += (sender, args) => form.MoveToCenter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ForceClose(){
|
public void ForceClose(){
|
||||||
trayIcon.Visible = false; // checked in FormClosing event
|
trayIcon.Visible = false; // checked in FormClosing event
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormNotification CreateNotificationForm(bool autoHide){
|
|
||||||
return new FormNotification(this, plugins, autoHide);
|
|
||||||
}
|
|
||||||
|
|
||||||
// window setup
|
// window setup
|
||||||
|
|
||||||
private void SetupWindow(){
|
private void RestoreWindow(){
|
||||||
Config.BrowserWindow.Restore(this, true);
|
Config.BrowserWindow.Restore(this, true);
|
||||||
prevState = WindowState;
|
prevState = WindowState;
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnBrowserReady(){
|
||||||
|
if (!isBrowserReady){
|
||||||
|
browser.Location = Point.Empty;
|
||||||
|
browser.Dock = DockStyle.Fill;
|
||||||
|
isBrowserReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateTrayIcon(){
|
private void UpdateTrayIcon(){
|
||||||
trayIcon.Visible = Config.TrayBehavior.ShouldDisplayIcon();
|
trayIcon.Visible = Config.TrayBehavior.ShouldDisplayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
// active event handlers
|
// active event handlers
|
||||||
|
|
||||||
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
private void browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
||||||
if (!e.IsLoading){
|
if (!e.IsLoading){
|
||||||
browser.AddWordToDictionary("tweetdeck");
|
foreach(string word in TwitterUtils.DictionaryWords){
|
||||||
browser.AddWordToDictionary("TweetDeck");
|
browser.AddWordToDictionary(word);
|
||||||
browser.AddWordToDictionary("tweetduck");
|
}
|
||||||
browser.AddWordToDictionary("TweetDuck");
|
|
||||||
browser.AddWordToDictionary("TD");
|
|
||||||
|
|
||||||
Invoke(new Action(SetupWindow));
|
BeginInvoke(new Action(OnBrowserReady));
|
||||||
browser.LoadingStateChanged -= Browser_LoadingStateChanged;
|
browser.LoadingStateChanged -= browser_LoadingStateChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
private void browser_FrameLoadStart(object sender, FrameLoadStartEventArgs e){
|
||||||
if (e.Frame.IsMain){
|
if (e.Frame.IsMain){
|
||||||
ScriptLoader.ExecuteFile(e.Frame, "code.js");
|
memoryUsageTracker.Stop();
|
||||||
|
|
||||||
if (plugins.HasAnyPlugin(PluginEnvironment.Browser)){
|
if (Config.ZoomLevel != 100){
|
||||||
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginBrowserScriptFile);
|
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel);
|
||||||
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
|
}
|
||||||
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser, true);
|
|
||||||
|
if (TwitterUtils.IsTwitterWebsite(e.Frame)){
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, "twitter.js");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
|
if (e.Frame.IsMain && TwitterUtils.IsTweetDeckWebsite(e.Frame)){
|
||||||
|
e.Frame.ExecuteJavaScriptAsync(TwitterUtils.BackgroundColorFix);
|
||||||
|
|
||||||
|
UpdateProperties(PropertyBridge.Environment.Browser);
|
||||||
|
TweetDeckBridge.RestoreSessionData(e.Frame);
|
||||||
|
ScriptLoader.ExecuteFile(e.Frame, "code.js");
|
||||||
|
ReinjectCustomCSS(Config.CustomBrowserCSS);
|
||||||
|
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser);
|
||||||
|
|
||||||
|
TweetDeckBridge.ResetStaticProperties();
|
||||||
|
|
||||||
|
if (Program.SystemConfig.EnableBrowserGCReload){
|
||||||
|
memoryUsageTracker.Start(this, e.Browser, Program.SystemConfig.BrowserMemoryThreshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void browser_LoadError(object sender, LoadErrorEventArgs e){
|
||||||
|
if (e.ErrorCode == CefErrorCode.Aborted){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.FailedUrl.StartsWith("http://td/", StringComparison.Ordinal)){
|
||||||
|
string errorPage = ScriptLoader.LoadResource("pages/error.html", true);
|
||||||
|
|
||||||
|
if (errorPage != null){
|
||||||
|
browser.LoadHtml(errorPage.Replace("{err}", BrowserUtils.GetErrorName(e.ErrorCode)), "http://td/error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerResize_Tick(object sender, EventArgs e){
|
||||||
|
FormBrowser_ResizeEnd(this, e); // also stops timer
|
||||||
|
}
|
||||||
|
|
||||||
private void FormBrowser_Activated(object sender, EventArgs e){
|
private void FormBrowser_Activated(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
if (!isLoaded)return;
|
||||||
|
|
||||||
trayIcon.HasNotifications = false;
|
trayIcon.HasNotifications = false;
|
||||||
|
|
||||||
|
if (!browser.Enabled){ // when taking a screenshot, the window is unfocused and
|
||||||
|
browser.Enabled = true; // the browser is disabled; if the user clicks back into
|
||||||
|
} // the window, enable the browser again
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormBrowser_LocationChanged(object sender, EventArgs e){
|
||||||
|
if (!isLoaded)return;
|
||||||
|
|
||||||
|
timerResize.Stop();
|
||||||
|
timerResize.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormBrowser_Resize(object sender, EventArgs e){
|
private void FormBrowser_Resize(object sender, EventArgs e){
|
||||||
@@ -145,12 +262,18 @@ namespace TweetDck.Core{
|
|||||||
FormBrowser_ResizeEnd(sender, e);
|
FormBrowser_ResizeEnd(sender, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
timerResize.Stop();
|
||||||
|
timerResize.Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
private void FormBrowser_ResizeEnd(object sender, EventArgs e){ // also triggers when the window moves
|
||||||
if (!isLoaded)return;
|
if (!isLoaded)return;
|
||||||
|
|
||||||
if (Location.X != -32000){
|
timerResize.Stop();
|
||||||
|
|
||||||
|
if (Location != ControlExtensions.InvisibleLocation){
|
||||||
Config.BrowserWindow.Save(this);
|
Config.BrowserWindow.Save(this);
|
||||||
Config.Save();
|
Config.Save();
|
||||||
}
|
}
|
||||||
@@ -165,126 +288,267 @@ namespace TweetDck.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
|
||||||
if (!isLoaded)return;
|
if (isLoaded && UpdateInstallerPath == null){
|
||||||
|
updates.CleanupDownload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
|
UpdateProperties(PropertyBridge.Environment.Browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Config_ZoomLevelChanged(object sender, EventArgs e){
|
||||||
|
BrowserUtils.SetZoomLevel(browser.GetBrowser(), Config.ZoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Config_TrayBehaviorChanged(object sender, EventArgs e){
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
private void trayIcon_ClickRestore(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
isLoaded = false;
|
|
||||||
Show();
|
Show();
|
||||||
SetupWindow();
|
RestoreWindow();
|
||||||
Activate();
|
Activate();
|
||||||
UpdateTrayIcon();
|
UpdateTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trayIcon_ClickClose(object sender, EventArgs e){
|
private void trayIcon_ClickClose(object sender, EventArgs e){
|
||||||
if (!isLoaded)return;
|
|
||||||
|
|
||||||
ForceClose();
|
ForceClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plugins_Reloaded(object sender, PluginLoadEventArgs e){
|
private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
|
||||||
ReloadBrowser();
|
if (e.HasErrors){
|
||||||
|
FormMessage.Error("Error Loading Plugins", "The following plugins will not be available until the issues are resolved:\n\n"+string.Join("\n\n", e.Errors), FormMessage.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoaded){
|
||||||
|
ReloadToTweetDeck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void plugins_Executed(object sender, PluginErrorEventArgs e){
|
||||||
|
if (e.HasErrors){
|
||||||
|
FormMessage.Error("Error Executing Plugins", "Failed to execute the following plugins:\n\n"+string.Join("\n\n", e.Errors), FormMessage.OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plugins_PluginChangedState(object sender, PluginChangedStateEventArgs e){
|
private void plugins_PluginChangedState(object sender, PluginChangedStateEventArgs e){
|
||||||
browser.ExecuteScriptAsync("window.TDPF_setPluginState", e.Plugin, e.IsEnabled ? 1 : 0); // ExecuteScriptAsync cannot handle boolean values as of yet
|
browser.ExecuteScriptAsync("window.TDPF_setPluginState", e.Plugin, e.IsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updates_UpdateAccepted(object sender, UpdateAcceptedEventArgs e){
|
private void updates_UpdateAccepted(object sender, UpdateAcceptedEventArgs e){
|
||||||
Hide();
|
this.InvokeAsyncSafe(() => {
|
||||||
|
FormManager.CloseAllDialogs();
|
||||||
|
|
||||||
FormUpdateDownload downloadForm = new FormUpdateDownload(e.UpdateInfo);
|
updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
|
||||||
downloadForm.MoveToCenter(this);
|
if (update.DownloadStatus == UpdateDownloadStatus.Done){
|
||||||
downloadForm.ShowDialog();
|
UpdateInstallerPath = update.InstallerPath;
|
||||||
|
}
|
||||||
|
|
||||||
if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
|
|
||||||
UpdateInstallerPath = downloadForm.InstallerPath;
|
|
||||||
ForceClose();
|
ForceClose();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
|
|
||||||
ForceClose();
|
private void updates_UpdateDismissed(object sender, UpdateDismissedEventArgs e){
|
||||||
|
this.InvokeAsyncSafe(() => {
|
||||||
|
Config.DismissedUpdate = e.VersionTag;
|
||||||
|
Config.Save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void soundNotification_PlaybackError(object sender, PlaybackErrorEventArgs e){
|
||||||
|
e.Ignore = true;
|
||||||
|
|
||||||
|
using(FormMessage form = new FormMessage("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, MessageBoxIcon.Error)){
|
||||||
|
form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
|
||||||
|
|
||||||
|
Button btnOpenSettings = form.AddButton("View Options");
|
||||||
|
btnOpenSettings.Width += 16;
|
||||||
|
btnOpenSettings.Location = new Point(btnOpenSettings.Location.X-16, btnOpenSettings.Location.Y);
|
||||||
|
|
||||||
|
if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnOpenSettings){
|
||||||
|
OpenSettings(typeof(TabSettingsSounds));
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
Show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
protected override void WndProc(ref Message m){
|
||||||
if (isLoaded && m.Msg == Program.WindowRestoreMessage){
|
if (isLoaded){
|
||||||
|
if (m.Msg == Program.WindowRestoreMessage){
|
||||||
|
if (WindowsUtils.CurrentProcessID == m.WParam.ToInt32()){
|
||||||
trayIcon_ClickRestore(trayIcon, new EventArgs());
|
trayIcon_ClickRestore(trayIcon, new EventArgs());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoaded && m.Msg == 0x210 && (m.WParam.ToInt32() & 0xFFFF) == 0x020B){ // WM_PARENTNOTIFY, WM_XBUTTONDOWN
|
return;
|
||||||
|
}
|
||||||
|
else if (m.Msg == Program.SubProcessMessage){
|
||||||
|
int processId = m.WParam.ToInt32();
|
||||||
|
|
||||||
|
if (WindowsUtils.IsChildProcess(processId)){ // child process is checked in two places for safety
|
||||||
|
BrowserProcesses.Link(m.LParam.ToInt32(), processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBrowserReady && m.Msg == NativeMethods.WM_PARENTNOTIFY && (m.WParam.ToInt32() & 0xFFFF) == NativeMethods.WM_XBUTTONDOWN){
|
||||||
|
if (videoPlayer != null && videoPlayer.Running){
|
||||||
|
videoPlayer.Close();
|
||||||
|
}
|
||||||
|
else{
|
||||||
browser.ExecuteScriptAsync("TDGF_onMouseClickExtra", (m.WParam.ToInt32() >> 16) & 0xFFFF);
|
browser.ExecuteScriptAsync("TDGF_onMouseClickExtra", (m.WParam.ToInt32() >> 16) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.WndProc(ref m);
|
base.WndProc(ref m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notification helpers
|
||||||
|
|
||||||
|
public FormNotificationMain CreateNotificationForm(bool enableContextMenu){
|
||||||
|
return new FormNotificationMain(this, plugins, enableContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PauseNotification(){
|
||||||
|
notification.PauseNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResumeNotification(){
|
||||||
|
notification.ResumeNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
// javascript calls
|
||||||
|
|
||||||
|
public void ReinjectCustomCSS(string css){
|
||||||
|
browser.ExecuteScriptAsync("TDGF_reinjectCustomCSS", css?.Replace(Environment.NewLine, " ") ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProperties(PropertyBridge.Environment environment){
|
||||||
|
browser.ExecuteScriptAsync(PropertyBridge.GenerateScript(environment));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReloadToTweetDeck(){
|
||||||
|
browser.ExecuteScriptAsync($"if(window.TDGF_reload)window.TDGF_reload();else window.location.href='{TwitterUtils.TweetDeckURL}'");
|
||||||
|
}
|
||||||
|
|
||||||
// callback handlers
|
// callback handlers
|
||||||
|
|
||||||
public void OpenSettings(){
|
public void OpenContextMenu(){
|
||||||
if (currentFormSettings != null){
|
contextMenu.Show(this, PointToClient(Cursor.Position));
|
||||||
currentFormSettings.BringToFront();
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
|
public void OpenSettings(){
|
||||||
|
OpenSettings(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenSettings(Type startTab){
|
||||||
|
if (!FormManager.TryBringToFront<FormSettings>()){
|
||||||
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
bool prevEnableUpdateCheck = Config.EnableUpdateCheck;
|
||||||
|
|
||||||
currentFormSettings = new FormSettings(this, plugins, updates);
|
FormSettings form = new FormSettings(this, plugins, updates, startTab);
|
||||||
|
|
||||||
currentFormSettings.FormClosed += (sender, args) => {
|
|
||||||
currentFormSettings = null;
|
|
||||||
|
|
||||||
|
form.FormClosed += (sender, args) => {
|
||||||
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
if (!prevEnableUpdateCheck && Config.EnableUpdateCheck){
|
||||||
Config.DismissedUpdate = string.Empty;
|
updates.DismissUpdate(string.Empty);
|
||||||
Config.Save();
|
|
||||||
updates.Check(false);
|
updates.Check(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Config.EnableTrayHighlight){
|
if (!Config.EnableTrayHighlight){
|
||||||
trayIcon.HasNotifications = false;
|
trayIcon.HasNotifications = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Program.SystemConfig.EnableBrowserGCReload){
|
||||||
|
memoryUsageTracker.Start(this, browser.GetBrowser(), Program.SystemConfig.BrowserMemoryThreshold);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
memoryUsageTracker.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateProperties(PropertyBridge.Environment.Browser);
|
||||||
|
|
||||||
|
notification.RequiresResize = true;
|
||||||
|
form.Dispose();
|
||||||
};
|
};
|
||||||
|
|
||||||
ShowChildForm(currentFormSettings);
|
ShowChildForm(form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenAbout(){
|
public void OpenAbout(){
|
||||||
if (currentFormAbout != null){
|
if (!FormManager.TryBringToFront<FormAbout>()){
|
||||||
currentFormAbout.BringToFront();
|
ShowChildForm(new FormAbout());
|
||||||
}
|
|
||||||
else{
|
|
||||||
currentFormAbout = new FormAbout();
|
|
||||||
currentFormAbout.FormClosed += (sender, args) => currentFormAbout = null;
|
|
||||||
ShowChildForm(currentFormAbout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenPlugins(){
|
public void OpenPlugins(){
|
||||||
if (currentFormPlugins != null){
|
if (!FormManager.TryBringToFront<FormPlugins>()){
|
||||||
currentFormPlugins.BringToFront();
|
ShowChildForm(new FormPlugins(plugins));
|
||||||
}
|
|
||||||
else{
|
|
||||||
currentFormPlugins = new FormPlugins(plugins);
|
|
||||||
currentFormPlugins.FormClosed += (sender, args) => currentFormPlugins = null;
|
|
||||||
ShowChildForm(currentFormPlugins);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnTweetNotification(){
|
public void OnTweetNotification(){ // may be called multiple times, once for each type of notification
|
||||||
if (Config.EnableTrayHighlight && !ContainsFocus){
|
if (Config.EnableTrayHighlight && !ContainsFocus){
|
||||||
trayIcon.HasNotifications = true;
|
trayIcon.HasNotifications = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PlayNotificationSound(){
|
||||||
|
if (Config.NotificationSoundPath.Length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundNotification == null){
|
||||||
|
soundNotification = new SoundNotification();
|
||||||
|
soundNotification.PlaybackError += soundNotification_PlaybackError;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundNotification.Play(Config.NotificationSoundPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayVideo(string url){
|
||||||
|
if (string.IsNullOrEmpty(url)){
|
||||||
|
videoPlayer?.Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoPlayer == null){
|
||||||
|
videoPlayer = new VideoPlayer(this);
|
||||||
|
|
||||||
|
videoPlayer.ProcessExited += (sender, args) => {
|
||||||
|
browser.GetBrowser().GetHost().SendFocusEvent(true);
|
||||||
|
HideVideoOverlay();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
videoPlayer.Launch(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleVideoPause(){
|
||||||
|
if (videoPlayer != null && videoPlayer.Running){
|
||||||
|
videoPlayer.TogglePause();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideVideoOverlay(){
|
||||||
|
browser.ExecuteScriptAsync("$('#td-video-player-overlay').remove()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTweetScreenshotReady(string html, int width, int height){
|
||||||
|
if (notificationScreenshotManager == null){
|
||||||
|
notificationScreenshotManager = new TweetScreenshotManager(this, plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationScreenshotManager.Trigger(html, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
public void DisplayTooltip(string text){
|
public void DisplayTooltip(string text){
|
||||||
if (string.IsNullOrEmpty(text)){
|
if (string.IsNullOrEmpty(text)){
|
||||||
toolTip.Hide(this);
|
toolTip.Hide(this);
|
||||||
@@ -296,16 +560,8 @@ namespace TweetDck.Core{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnImagePasted(){
|
public void TriggerTweetScreenshot(){
|
||||||
browser.ExecuteScriptAsync("TDGF_tryPasteImage", new object[0]);
|
browser.ExecuteScriptAsync("TDGF_triggerScreenshot()");
|
||||||
}
|
|
||||||
|
|
||||||
public void OnImagePastedFinish(){
|
|
||||||
browser.ExecuteScriptAsync("TDGF_tryPasteImageFinish", new object[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReloadBrowser(){
|
|
||||||
browser.ExecuteScriptAsync("window.location.reload()");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,11 +117,13 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<data name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing">
|
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing">
|
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>112, 17</value>
|
<value>112, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
|
<metadata name="timerResize.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>202, 17</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
||||||
25
Core/FormManager.cs
Normal file
25
Core/FormManager.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core{
|
||||||
|
static class FormManager{
|
||||||
|
public static bool TryBringToFront<T>() where T : Form{
|
||||||
|
T form = Application.OpenForms.OfType<T>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (form != null){
|
||||||
|
form.BringToFront();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CloseAllDialogs(){
|
||||||
|
foreach(Form form in Application.OpenForms.Cast<Form>().Reverse()){
|
||||||
|
if (form is FormSettings || form is FormPlugins || form is FormAbout){
|
||||||
|
form.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,368 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using CefSharp;
|
|
||||||
using CefSharp.WinForms;
|
|
||||||
using TweetDck.Configuration;
|
|
||||||
using TweetDck.Core.Handling;
|
|
||||||
using TweetDck.Resources;
|
|
||||||
using TweetDck.Core.Utils;
|
|
||||||
using TweetDck.Plugins;
|
|
||||||
|
|
||||||
namespace TweetDck.Core{
|
|
||||||
sealed partial class FormNotification : Form{
|
|
||||||
private const string NotificationScriptFile = "notification.js";
|
|
||||||
|
|
||||||
private static readonly string NotificationScriptIdentifier = ScriptLoader.GetRootIdentifier(NotificationScriptFile);
|
|
||||||
private static readonly string PluginScriptIdentifier = ScriptLoader.GetRootIdentifier(PluginManager.PluginNotificationScriptFile);
|
|
||||||
|
|
||||||
public Func<bool> CanMoveWindow = () => true;
|
|
||||||
|
|
||||||
private readonly Form owner;
|
|
||||||
private readonly PluginManager plugins;
|
|
||||||
private readonly ChromiumWebBrowser browser;
|
|
||||||
|
|
||||||
private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
|
|
||||||
private readonly bool autoHide;
|
|
||||||
private int timeLeft, totalTime;
|
|
||||||
|
|
||||||
private readonly NativeMethods.HookProc mouseHookDelegate;
|
|
||||||
private IntPtr mouseHook;
|
|
||||||
|
|
||||||
private bool? prevDisplayTimer;
|
|
||||||
private int? prevFontSize;
|
|
||||||
|
|
||||||
private bool RequiresResize{
|
|
||||||
get{
|
|
||||||
return !prevDisplayTimer.HasValue || !prevFontSize.HasValue || prevDisplayTimer != Program.UserConfig.DisplayNotificationTimer || prevFontSize != TweetNotification.FontSizeLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
|
||||||
if (value){
|
|
||||||
prevDisplayTimer = null;
|
|
||||||
prevFontSize = null;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
prevDisplayTimer = Program.UserConfig.DisplayNotificationTimer;
|
|
||||||
prevFontSize = TweetNotification.FontSizeLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly string notificationJS;
|
|
||||||
private readonly string pluginJS;
|
|
||||||
|
|
||||||
protected override bool ShowWithoutActivation{
|
|
||||||
get{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool FreezeTimer { get; set; }
|
|
||||||
public bool ContextMenuOpen { get; set; }
|
|
||||||
public string CurrentUrl { get; private set; }
|
|
||||||
|
|
||||||
public EventHandler Initialized;
|
|
||||||
private bool isInitialized;
|
|
||||||
|
|
||||||
private static int BaseClientWidth{
|
|
||||||
get{
|
|
||||||
int level = TweetNotification.FontSizeLevel;
|
|
||||||
return level == 0 ? 284 : (int)Math.Round(284.0*(1.0+0.05*level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int BaseClientHeight{
|
|
||||||
get{
|
|
||||||
int level = TweetNotification.FontSizeLevel;
|
|
||||||
return level == 0 ? 118 : (int)Math.Round(118.0*(1.0+0.075*level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormNotification(FormBrowser owner, PluginManager pluginManager, bool autoHide){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
Text = Program.BrandName;
|
|
||||||
|
|
||||||
this.owner = owner;
|
|
||||||
this.plugins = pluginManager;
|
|
||||||
this.autoHide = autoHide;
|
|
||||||
|
|
||||||
owner.FormClosed += (sender, args) => Close();
|
|
||||||
|
|
||||||
notificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
|
|
||||||
pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
|
|
||||||
|
|
||||||
browser = new ChromiumWebBrowser("about:blank"){
|
|
||||||
MenuHandler = new ContextMenuNotification(this, autoHide),
|
|
||||||
LifeSpanHandler = new LifeSpanHandler()
|
|
||||||
};
|
|
||||||
|
|
||||||
browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
|
|
||||||
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
|
||||||
browser.RegisterJsObject("$TD", new TweetDeckBridge(owner, this));
|
|
||||||
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
|
||||||
|
|
||||||
panelBrowser.Controls.Add(browser);
|
|
||||||
|
|
||||||
if (autoHide){
|
|
||||||
Program.UserConfig.MuteToggled += Config_MuteToggled;
|
|
||||||
Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled;
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseHookDelegate = MouseHookProc;
|
|
||||||
|
|
||||||
Disposed += FormNotification_Disposed;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void WndProc(ref Message m){
|
|
||||||
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanMoveWindow()){ // WM_SYSCOMMAND, SC_MOVE
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.WndProc(ref m);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mouse wheel hook
|
|
||||||
|
|
||||||
private void StartMouseHook(){
|
|
||||||
if (mouseHook == IntPtr.Zero){
|
|
||||||
mouseHook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, mouseHookDelegate, IntPtr.Zero, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopMouseHook(){
|
|
||||||
if (mouseHook != IntPtr.Zero){
|
|
||||||
NativeMethods.UnhookWindowsHookEx(mouseHook);
|
|
||||||
mouseHook = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam){
|
|
||||||
if (!ContainsFocus && wParam.ToInt32() == NativeMethods.WH_MOUSEWHEEL && browser.Bounds.Contains(PointToClient(Cursor.Position))){
|
|
||||||
// fuck it, Activate() doesn't work with this
|
|
||||||
Point prevPos = Cursor.Position;
|
|
||||||
Cursor.Position = PointToScreen(new Point(0, -1));
|
|
||||||
NativeMethods.SimulateMouseClick(NativeMethods.MouseButton.Left);
|
|
||||||
Cursor.Position = prevPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeMethods.CallNextHookEx(mouseHook, nCode, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
// event handlers
|
|
||||||
|
|
||||||
private void timerHideProgress_Tick(object sender, EventArgs e){
|
|
||||||
if (Bounds.Contains(Cursor.Position) || FreezeTimer || ContextMenuOpen)return;
|
|
||||||
|
|
||||||
timeLeft -= timerProgress.Interval;
|
|
||||||
|
|
||||||
int value = (int)Math.Round(1025.0*(totalTime-timeLeft)/totalTime);
|
|
||||||
progressBarTimer.SetValueInstant(Math.Min(1000, Math.Max(0, Program.UserConfig.NotificationTimerCountDown ? 1000-value : value)));
|
|
||||||
|
|
||||||
if (timeLeft <= 0){
|
|
||||||
FinishCurrentTweet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Config_MuteToggled(object sender, EventArgs e){
|
|
||||||
if (Program.UserConfig.MuteNotifications){
|
|
||||||
HideNotification(true);
|
|
||||||
}
|
|
||||||
else if (tweetQueue.Count > 0){
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Browser_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e){
|
|
||||||
if (e.IsBrowserInitialized && Initialized != null){
|
|
||||||
Initialized(this, new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
|
||||||
if (!e.Frame.IsMain)return;
|
|
||||||
|
|
||||||
if (!isInitialized && !Program.UserConfig.NotificationLegacyLoad){
|
|
||||||
isInitialized = true;
|
|
||||||
|
|
||||||
if (Initialized != null){
|
|
||||||
Initialized(this, new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (notificationJS != null && browser.Address != "about:blank"){
|
|
||||||
ScriptLoader.ExecuteScript(e.Frame, notificationJS, NotificationScriptIdentifier);
|
|
||||||
|
|
||||||
if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){
|
|
||||||
ScriptLoader.ExecuteScript(e.Frame, pluginJS, PluginScriptIdentifier);
|
|
||||||
ScriptLoader.ExecuteFile(e.Frame, PluginManager.PluginGlobalScriptFile);
|
|
||||||
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FormNotification_FormClosing(object sender, FormClosingEventArgs e){
|
|
||||||
if (e.CloseReason == CloseReason.UserClosing){
|
|
||||||
HideNotification(false);
|
|
||||||
tweetQueue.Clear();
|
|
||||||
e.Cancel = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FormNotification_Disposed(object sender, EventArgs e){
|
|
||||||
browser.Dispose();
|
|
||||||
StopMouseHook();
|
|
||||||
}
|
|
||||||
|
|
||||||
// notification methods
|
|
||||||
|
|
||||||
public void ShowNotification(TweetNotification notification){
|
|
||||||
if (Program.UserConfig.MuteNotifications){
|
|
||||||
tweetQueue.Enqueue(notification);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
tweetQueue.Enqueue(notification);
|
|
||||||
UpdateTitle();
|
|
||||||
|
|
||||||
if (totalTime == 0){
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowNotificationForSettings(bool reset){
|
|
||||||
if (reset){
|
|
||||||
LoadTweet(TweetNotification.ExampleTweet);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
MoveToVisibleLocation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideNotification(bool loadBlank){
|
|
||||||
if (loadBlank || Program.UserConfig.NotificationLegacyLoad){
|
|
||||||
browser.LoadHtml("", "about:blank");
|
|
||||||
}
|
|
||||||
|
|
||||||
Location = new Point(-32000, -32000);
|
|
||||||
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
|
||||||
timerProgress.Stop();
|
|
||||||
totalTime = 0;
|
|
||||||
|
|
||||||
StopMouseHook();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnNotificationReady(){
|
|
||||||
UpdateTitle();
|
|
||||||
MoveToVisibleLocation();
|
|
||||||
timerProgress.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FinishCurrentTweet(){
|
|
||||||
if (tweetQueue.Count > 0){
|
|
||||||
LoadNextNotification();
|
|
||||||
}
|
|
||||||
else if (autoHide){
|
|
||||||
HideNotification(true);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
timerProgress.Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadNextNotification(){
|
|
||||||
LoadTweet(tweetQueue.Dequeue());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadTweet(TweetNotification tweet){
|
|
||||||
CurrentUrl = tweet.Url;
|
|
||||||
|
|
||||||
timerProgress.Stop();
|
|
||||||
totalTime = timeLeft = tweet.GetDisplayDuration(Program.UserConfig.NotificationDurationValue);
|
|
||||||
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
|
||||||
|
|
||||||
browser.LoadHtml(tweet.GenerateHtml(), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks);
|
|
||||||
|
|
||||||
if (Program.UserConfig.NotificationLegacyLoad){
|
|
||||||
OnNotificationReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MoveToVisibleLocation(){
|
|
||||||
UserConfig config = Program.UserConfig;
|
|
||||||
|
|
||||||
if (RequiresResize){
|
|
||||||
RequiresResize = false;
|
|
||||||
|
|
||||||
if (config.DisplayNotificationTimer){
|
|
||||||
ClientSize = new Size(BaseClientWidth, BaseClientHeight+4);
|
|
||||||
progressBarTimer.Visible = true;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
ClientSize = new Size(BaseClientWidth, BaseClientHeight);
|
|
||||||
progressBarTimer.Visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
panelBrowser.Height = BaseClientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
Screen screen = Screen.FromControl(owner);
|
|
||||||
|
|
||||||
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
|
||||||
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsReactivating = Location.X == -32000;
|
|
||||||
int edgeDist = config.NotificationEdgeDistance;
|
|
||||||
|
|
||||||
switch(config.NotificationPosition){
|
|
||||||
case TweetNotification.Position.TopLeft:
|
|
||||||
Location = new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+edgeDist);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.TopRight:
|
|
||||||
Location = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.BottomLeft:
|
|
||||||
Location = new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.BottomRight:
|
|
||||||
Location = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TweetNotification.Position.Custom:
|
|
||||||
if (!config.IsCustomNotificationPositionSet){
|
|
||||||
config.CustomNotificationPosition = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
|
||||||
config.Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
Location = config.CustomNotificationPosition;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsReactivating){
|
|
||||||
NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
StartMouseHook();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTitle(){
|
|
||||||
Text = tweetQueue.Count > 0 ? Program.BrandName+" ("+tweetQueue.Count+" more left)" : Program.BrandName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DisplayTooltip(string text){
|
|
||||||
if (string.IsNullOrEmpty(text)){
|
|
||||||
toolTip.Hide(this);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Point position = PointToClient(Cursor.Position);
|
|
||||||
position.Offset(20, 5);
|
|
||||||
toolTip.Show(text, this, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +1,77 @@
|
|||||||
using CefSharp;
|
using System;
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Utils;
|
using CefSharp;
|
||||||
|
using TweetDuck.Core.Bridge;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
abstract class ContextMenuBase : IContextMenuHandler{
|
abstract class ContextMenuBase : IContextMenuHandler{
|
||||||
|
protected static readonly bool HasDevTools = File.Exists(Path.Combine(Program.ProgramPath, "devtools_resources.pak"));
|
||||||
|
|
||||||
|
private static TwitterUtils.ImageQuality ImageQuality => Program.UserConfig.TwitterImageQuality;
|
||||||
|
|
||||||
|
private static string GetLink(IContextMenuParams parameters){
|
||||||
|
return string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetImage(IContextMenuParams parameters){
|
||||||
|
return string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage) ? parameters.SourceUrl : TweetDeckBridge.LastRightClickedImage;
|
||||||
|
}
|
||||||
|
|
||||||
private const int MenuOpenLinkUrl = 26500;
|
private const int MenuOpenLinkUrl = 26500;
|
||||||
private const int MenuCopyLinkUrl = 26501;
|
private const int MenuCopyLinkUrl = 26501;
|
||||||
private const int MenuOpenImage = 26502;
|
private const int MenuCopyUsername = 26502;
|
||||||
private const int MenuSaveImage = 26503;
|
private const int MenuOpenImageUrl = 26503;
|
||||||
private const int MenuCopyImageUrl = 26504;
|
private const int MenuCopyImageUrl = 26504;
|
||||||
|
private const int MenuSaveImage = 26505;
|
||||||
|
private const int MenuSaveAllImages = 26506;
|
||||||
|
private const int MenuOpenDevTools = 26599;
|
||||||
|
|
||||||
|
private readonly Form form;
|
||||||
|
|
||||||
|
private string lastHighlightedTweetAuthor;
|
||||||
|
private string[] lastHighlightedTweetImageList;
|
||||||
|
|
||||||
|
protected ContextMenuBase(Form form){
|
||||||
|
this.form = form;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal)){
|
bool hasTweetImage = !string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedImage);
|
||||||
|
lastHighlightedTweetAuthor = TweetDeckBridge.LastHighlightedTweetAuthor;
|
||||||
|
lastHighlightedTweetImageList = TweetDeckBridge.LastHighlightedTweetImages;
|
||||||
|
|
||||||
|
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
||||||
|
lastHighlightedTweetAuthor = string.Empty;
|
||||||
|
lastHighlightedTweetImageList = StringUtils.EmptyArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Link) && !parameters.UnfilteredLinkUrl.EndsWith("tweetdeck.twitter.com/#", StringComparison.Ordinal) && !hasTweetImage){
|
||||||
|
if (TwitterUtils.RegexAccount.IsMatch(parameters.UnfilteredLinkUrl)){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open account in browser");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy account address");
|
||||||
|
model.AddItem((CefMenuCommand)MenuCopyUsername, "Copy account username");
|
||||||
|
}
|
||||||
|
else{
|
||||||
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open link in browser");
|
model.AddItem((CefMenuCommand)MenuOpenLinkUrl, "Open link in browser");
|
||||||
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy link address");
|
model.AddItem((CefMenuCommand)MenuCopyLinkUrl, "Copy link address");
|
||||||
|
}
|
||||||
|
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents){
|
if ((parameters.TypeFlags.HasFlag(ContextMenuType.Media) && parameters.HasImageContents) || hasTweetImage){
|
||||||
model.AddItem((CefMenuCommand)MenuOpenImage, "Open image in browser");
|
model.AddItem((CefMenuCommand)MenuOpenImageUrl, "Open image in browser");
|
||||||
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
|
|
||||||
model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
|
model.AddItem((CefMenuCommand)MenuCopyImageUrl, "Copy image address");
|
||||||
|
model.AddItem((CefMenuCommand)MenuSaveImage, "Save image as...");
|
||||||
|
|
||||||
|
if (lastHighlightedTweetImageList.Length > 1){
|
||||||
|
model.AddItem((CefMenuCommand)MenuSaveAllImages, "Save all images as...");
|
||||||
|
}
|
||||||
|
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,50 +83,55 @@ namespace TweetDck.Core.Handling{
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuCopyLinkUrl:
|
case MenuCopyLinkUrl:
|
||||||
Clipboard.SetText(string.IsNullOrEmpty(TweetDeckBridge.LastRightClickedLink) ? parameters.UnfilteredLinkUrl : TweetDeckBridge.LastRightClickedLink, TextDataFormat.UnicodeText);
|
SetClipboardText(GetLink(parameters));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuOpenImage:
|
case MenuOpenImageUrl:
|
||||||
BrowserUtils.OpenExternalBrowser(parameters.SourceUrl);
|
BrowserUtils.OpenExternalBrowser(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuSaveImage:
|
case MenuSaveImage:
|
||||||
string fileName = GetImageFileName(parameters.SourceUrl);
|
TwitterUtils.DownloadImage(GetImage(parameters), lastHighlightedTweetAuthor, ImageQuality);
|
||||||
string extension = Path.GetExtension(fileName);
|
break;
|
||||||
string saveTarget;
|
|
||||||
|
|
||||||
using(SaveFileDialog dialog = new SaveFileDialog{
|
|
||||||
AutoUpgradeEnabled = true,
|
|
||||||
OverwritePrompt = true,
|
|
||||||
Title = "Save image",
|
|
||||||
FileName = fileName,
|
|
||||||
Filter = "Image ("+(string.IsNullOrEmpty(extension) ? "unknown" : extension)+")|*.*"
|
|
||||||
}){
|
|
||||||
saveTarget = dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveTarget != null){
|
|
||||||
BrowserUtils.DownloadFileAsync(parameters.SourceUrl, saveTarget, ex => {
|
|
||||||
MessageBox.Show("An error occurred while downloading the image: "+ex.Message, Program.BrandName+" Has Failed :(", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case MenuSaveAllImages:
|
||||||
|
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthor, ImageQuality);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuCopyImageUrl:
|
case MenuCopyImageUrl:
|
||||||
Clipboard.SetText(parameters.SourceUrl, TextDataFormat.UnicodeText);
|
SetClipboardText(TwitterUtils.GetImageLink(GetImage(parameters), ImageQuality));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuCopyUsername:
|
||||||
|
Match match = TwitterUtils.RegexAccount.Match(parameters.UnfilteredLinkUrl);
|
||||||
|
SetClipboardText(match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MenuOpenDevTools:
|
||||||
|
browserControl.ShowDevTools();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){}
|
public virtual void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
|
||||||
|
TweetDeckBridge.LastRightClickedLink = string.Empty;
|
||||||
|
TweetDeckBridge.LastRightClickedImage = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
public virtual bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void SetClipboardText(string text){
|
||||||
|
form.InvokeAsyncSafe(() => WindowsUtils.SetClipboard(text, TextDataFormat.UnicodeText));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void AddDebugMenuItems(IMenuModel model){
|
||||||
|
model.AddItem((CefMenuCommand)MenuOpenDevTools, "Open dev tools");
|
||||||
|
}
|
||||||
|
|
||||||
protected static void RemoveSeparatorIfLast(IMenuModel model){
|
protected static void RemoveSeparatorIfLast(IMenuModel model){
|
||||||
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
if (model.Count > 0 && model.GetTypeAt(model.Count-1) == MenuItemType.Separator){
|
||||||
model.RemoveAt(model.Count-1);
|
model.RemoveAt(model.Count-1);
|
||||||
@@ -89,21 +143,5 @@ namespace TweetDck.Core.Handling{
|
|||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetImageFileName(string url){
|
|
||||||
// twimg adds a colon after file extension
|
|
||||||
int dot = url.LastIndexOf('.');
|
|
||||||
|
|
||||||
if (dot != -1){
|
|
||||||
int colon = url.IndexOf(':', dot);
|
|
||||||
|
|
||||||
if (colon != -1){
|
|
||||||
url = url.Substring(0, colon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return file name
|
|
||||||
return BrowserUtils.GetFileNameFromUrl(url) ?? "unknown";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Core.Bridge;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
class ContextMenuBrowser : ContextMenuBase{
|
class ContextMenuBrowser : ContextMenuBase{
|
||||||
private const int MenuGlobal = 26600;
|
private const int MenuGlobal = 26600;
|
||||||
private const int MenuMute = 26601;
|
private const int MenuMute = 26601;
|
||||||
@@ -15,13 +16,20 @@ namespace TweetDck.Core.Handling{
|
|||||||
private const int MenuCopyTweetUrl = 26611;
|
private const int MenuCopyTweetUrl = 26611;
|
||||||
private const int MenuOpenQuotedTweetUrl = 26612;
|
private const int MenuOpenQuotedTweetUrl = 26612;
|
||||||
private const int MenuCopyQuotedTweetUrl = 26613;
|
private const int MenuCopyQuotedTweetUrl = 26613;
|
||||||
|
private const int MenuScreenshotTweet = 26614;
|
||||||
|
|
||||||
|
private const string TitleReloadBrowser = "Reload browser";
|
||||||
|
private const string TitleMuteNotifications = "Mute notifications";
|
||||||
|
private const string TitleSettings = "Options";
|
||||||
|
private const string TitlePlugins = "Plugins";
|
||||||
|
private const string TitleAboutProgram = "About "+Program.BrandName;
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
private readonly FormBrowser form;
|
||||||
|
|
||||||
private string lastHighlightedTweet;
|
private string lastHighlightedTweet;
|
||||||
private string lastHighlightedQuotedTweet;
|
private string lastHighlightedQuotedTweet;
|
||||||
|
|
||||||
public ContextMenuBrowser(FormBrowser form){
|
public ContextMenuBrowser(FormBrowser form) : base(form){
|
||||||
this.form = form;
|
this.form = form;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,14 +40,24 @@ namespace TweetDck.Core.Handling{
|
|||||||
model.Remove(CefMenuCommand.ViewSource);
|
model.Remove(CefMenuCommand.ViewSource);
|
||||||
RemoveSeparatorIfLast(model);
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection)){
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
||||||
|
|
||||||
lastHighlightedTweet = TweetDeckBridge.LastHighlightedTweet;
|
lastHighlightedTweet = TweetDeckBridge.LastHighlightedTweet;
|
||||||
lastHighlightedQuotedTweet = TweetDeckBridge.LastHighlightedQuotedTweet;
|
lastHighlightedQuotedTweet = TweetDeckBridge.LastHighlightedQuotedTweet;
|
||||||
|
|
||||||
|
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
|
||||||
|
lastHighlightedTweet = string.Empty;
|
||||||
|
lastHighlightedQuotedTweet = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(lastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
|
if (!string.IsNullOrEmpty(lastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
|
||||||
model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
|
model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
|
||||||
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
||||||
|
model.AddItem((CefMenuCommand)MenuScreenshotTweet, "Screenshot tweet to clipboard");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){
|
if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
@@ -55,17 +73,24 @@ namespace TweetDck.Core.Handling{
|
|||||||
|
|
||||||
IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu((CefMenuCommand)MenuGlobal, Program.BrandName);
|
IMenuModel globalMenu = model.Count == 0 ? model : model.AddSubMenu((CefMenuCommand)MenuGlobal, Program.BrandName);
|
||||||
|
|
||||||
globalMenu.AddItem(CefMenuCommand.Reload, "Reload browser");
|
globalMenu.AddItem(CefMenuCommand.Reload, TitleReloadBrowser);
|
||||||
globalMenu.AddCheckItem((CefMenuCommand)MenuMute, "Mute notifications");
|
globalMenu.AddCheckItem((CefMenuCommand)MenuMute, TitleMuteNotifications);
|
||||||
globalMenu.SetChecked((CefMenuCommand)MenuMute, Program.UserConfig.MuteNotifications);
|
globalMenu.SetChecked((CefMenuCommand)MenuMute, Program.UserConfig.MuteNotifications);
|
||||||
globalMenu.AddSeparator();
|
globalMenu.AddSeparator();
|
||||||
|
|
||||||
globalMenu.AddItem((CefMenuCommand)MenuSettings, "Settings");
|
globalMenu.AddItem((CefMenuCommand)MenuSettings, TitleSettings);
|
||||||
globalMenu.AddItem((CefMenuCommand)MenuPlugins, "Plugins");
|
globalMenu.AddItem((CefMenuCommand)MenuPlugins, TitlePlugins);
|
||||||
globalMenu.AddItem((CefMenuCommand)MenuAbout, "About "+Program.BrandName);
|
globalMenu.AddItem((CefMenuCommand)MenuAbout, TitleAboutProgram);
|
||||||
|
|
||||||
|
if (HasDevTools){
|
||||||
|
globalMenu.AddSeparator();
|
||||||
|
AddDebugMenuItems(globalMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoveSeparatorIfLast(model);
|
||||||
|
}
|
||||||
|
|
||||||
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
if (base.OnContextMenuCommand(browserControl, browser, frame, parameters, commandId, eventFlags)){
|
if (base.OnContextMenuCommand(browserControl, browser, frame, parameters, commandId, eventFlags)){
|
||||||
return true;
|
return true;
|
||||||
@@ -73,27 +98,23 @@ namespace TweetDck.Core.Handling{
|
|||||||
|
|
||||||
switch((int)commandId){
|
switch((int)commandId){
|
||||||
case (int)CefMenuCommand.Reload:
|
case (int)CefMenuCommand.Reload:
|
||||||
frame.ExecuteJavaScriptAsync("window.location.href = 'https://tweetdeck.twitter.com'");
|
form.InvokeAsyncSafe(form.ReloadToTweetDeck);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuSettings:
|
case MenuSettings:
|
||||||
form.InvokeSafe(form.OpenSettings);
|
form.InvokeAsyncSafe(form.OpenSettings);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuAbout:
|
case MenuAbout:
|
||||||
form.InvokeSafe(form.OpenAbout);
|
form.InvokeAsyncSafe(form.OpenAbout);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuPlugins:
|
case MenuPlugins:
|
||||||
form.InvokeSafe(form.OpenPlugins);
|
form.InvokeAsyncSafe(form.OpenPlugins);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuMute:
|
case MenuMute:
|
||||||
form.InvokeSafe(() => {
|
form.InvokeAsyncSafe(ToggleMuteNotifications);
|
||||||
Program.UserConfig.MuteNotifications = !Program.UserConfig.MuteNotifications;
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuOpenTweetUrl:
|
case MenuOpenTweetUrl:
|
||||||
@@ -101,7 +122,11 @@ namespace TweetDck.Core.Handling{
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuCopyTweetUrl:
|
case MenuCopyTweetUrl:
|
||||||
Clipboard.SetText(lastHighlightedTweet, TextDataFormat.UnicodeText);
|
SetClipboardText(lastHighlightedTweet);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MenuScreenshotTweet:
|
||||||
|
form.InvokeAsyncSafe(form.TriggerTweetScreenshot);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuOpenQuotedTweetUrl:
|
case MenuOpenQuotedTweetUrl:
|
||||||
@@ -109,11 +134,33 @@ namespace TweetDck.Core.Handling{
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuCopyQuotedTweetUrl:
|
case MenuCopyQuotedTweetUrl:
|
||||||
Clipboard.SetText(lastHighlightedQuotedTweet, TextDataFormat.UnicodeText);
|
SetClipboardText(lastHighlightedQuotedTweet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ContextMenu CreateMenu(FormBrowser form){
|
||||||
|
ContextMenu menu = new ContextMenu();
|
||||||
|
|
||||||
|
menu.MenuItems.Add(TitleReloadBrowser, (sender, args) => form.ReloadToTweetDeck());
|
||||||
|
menu.MenuItems.Add(TitleMuteNotifications, (sender, args) => ToggleMuteNotifications());
|
||||||
|
menu.MenuItems.Add("-");
|
||||||
|
menu.MenuItems.Add(TitleSettings, (sender, args) => form.OpenSettings());
|
||||||
|
menu.MenuItems.Add(TitlePlugins, (sender, args) => form.OpenPlugins());
|
||||||
|
menu.MenuItems.Add(TitleAboutProgram, (sender, args) => form.OpenAbout());
|
||||||
|
|
||||||
|
menu.Popup += (sender, args) => {
|
||||||
|
menu.MenuItems[1].Checked = Program.UserConfig.MuteNotifications;
|
||||||
|
};
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ToggleMuteNotifications(){
|
||||||
|
Program.UserConfig.MuteNotifications = !Program.UserConfig.MuteNotifications;
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
using System.Windows.Forms;
|
using CefSharp;
|
||||||
using CefSharp;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Core.Notification;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDuck.Core.Handling{
|
||||||
class ContextMenuNotification : ContextMenuBase{
|
class ContextMenuNotification : ContextMenuBase{
|
||||||
private const int MenuSkipTweet = 26600;
|
private const int MenuSkipTweet = 26600;
|
||||||
private const int MenuFreeze = 26601;
|
private const int MenuFreeze = 26601;
|
||||||
private const int MenuCopyTweetUrl = 26602;
|
private const int MenuCopyTweetUrl = 26602;
|
||||||
private const int MenuCopyTweetEmbeddedUrl = 26603;
|
private const int MenuCopyQuotedTweetUrl = 26603;
|
||||||
|
|
||||||
private readonly FormNotification form;
|
private readonly FormNotificationBase form;
|
||||||
private readonly bool enableCustomMenu;
|
private readonly bool enableCustomMenu;
|
||||||
|
|
||||||
public ContextMenuNotification(FormNotification form, bool enableCustomMenu){
|
public ContextMenuNotification(FormNotificationBase form, bool enableCustomMenu) : base(form){
|
||||||
this.form = form;
|
this.form = form;
|
||||||
this.enableCustomMenu = enableCustomMenu;
|
this.enableCustomMenu = enableCustomMenu;
|
||||||
}
|
}
|
||||||
@@ -20,27 +20,37 @@ namespace TweetDck.Core.Handling{
|
|||||||
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
|
||||||
model.Clear();
|
model.Clear();
|
||||||
|
|
||||||
|
if (parameters.TypeFlags.HasFlag(ContextMenuType.Selection)){
|
||||||
|
model.AddItem(CefMenuCommand.Copy, "Copy");
|
||||||
|
model.AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
||||||
|
|
||||||
if (enableCustomMenu){
|
if (enableCustomMenu){
|
||||||
model.AddItem((CefMenuCommand)MenuSkipTweet, "Skip tweet");
|
model.AddItem((CefMenuCommand)MenuSkipTweet, "Skip tweet");
|
||||||
model.AddCheckItem((CefMenuCommand)MenuFreeze, "Freeze");
|
model.AddCheckItem((CefMenuCommand)MenuFreeze, "Freeze");
|
||||||
model.SetChecked((CefMenuCommand)MenuFreeze, form.FreezeTimer);
|
model.SetChecked((CefMenuCommand)MenuFreeze, form.FreezeTimer);
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(form.CurrentUrl)){
|
if (!string.IsNullOrEmpty(form.CurrentTweetUrl)){
|
||||||
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(TweetDeckBridge.NotificationTweetEmbedded)){
|
if (!string.IsNullOrEmpty(form.CurrentQuoteUrl)){
|
||||||
model.AddItem((CefMenuCommand)MenuCopyTweetEmbeddedUrl, "Copy quoted tweet address");
|
model.AddItem((CefMenuCommand)MenuCopyQuotedTweetUrl, "Copy quoted tweet address");
|
||||||
}
|
}
|
||||||
|
|
||||||
model.AddSeparator();
|
model.AddSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);
|
if (HasDevTools){
|
||||||
|
AddDebugMenuItems(model);
|
||||||
|
}
|
||||||
|
|
||||||
RemoveSeparatorIfLast(model);
|
RemoveSeparatorIfLast(model);
|
||||||
|
|
||||||
form.InvokeSafe(() => form.ContextMenuOpen = true);
|
form.InvokeAsyncSafe(() => form.ContextMenuOpen = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
|
||||||
@@ -50,19 +60,19 @@ namespace TweetDck.Core.Handling{
|
|||||||
|
|
||||||
switch((int)commandId){
|
switch((int)commandId){
|
||||||
case MenuSkipTweet:
|
case MenuSkipTweet:
|
||||||
form.InvokeSafe(form.FinishCurrentTweet);
|
form.InvokeAsyncSafe(form.FinishCurrentNotification);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuFreeze:
|
case MenuFreeze:
|
||||||
form.InvokeSafe(() => form.FreezeTimer = !form.FreezeTimer);
|
form.InvokeAsyncSafe(() => form.FreezeTimer = !form.FreezeTimer);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuCopyTweetUrl:
|
case MenuCopyTweetUrl:
|
||||||
Clipboard.SetText(form.CurrentUrl, TextDataFormat.UnicodeText);
|
SetClipboardText(form.CurrentTweetUrl);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MenuCopyTweetEmbeddedUrl:
|
case MenuCopyQuotedTweetUrl:
|
||||||
Clipboard.SetText(TweetDeckBridge.NotificationTweetEmbedded, TextDataFormat.UnicodeText);
|
SetClipboardText(form.CurrentQuoteUrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +81,7 @@ namespace TweetDck.Core.Handling{
|
|||||||
|
|
||||||
public override void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
|
public override void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame){
|
||||||
base.OnContextMenuDismissed(browserControl, browser, frame);
|
base.OnContextMenuDismissed(browserControl, browser, frame);
|
||||||
form.InvokeSafe(() => form.ContextMenuOpen = false);
|
form.InvokeAsyncSafe(() => form.ContextMenuOpen = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
using CefSharp;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
|
||||||
class DialogHandlerBrowser : IDialogHandler{
|
|
||||||
private readonly FormBrowser form;
|
|
||||||
|
|
||||||
public DialogHandlerBrowser(FormBrowser form){
|
|
||||||
this.form = form;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnFileDialog(IWebBrowser browserControl, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List<string> acceptFilters, int selectedAcceptFilter, IFileDialogCallback callback){
|
|
||||||
if (!string.IsNullOrEmpty(TweetDeckBridge.ClipboardImagePath)){
|
|
||||||
callback.Continue(selectedAcceptFilter, new List<string>{ TweetDeckBridge.ClipboardImagePath });
|
|
||||||
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
TweetDeckBridge.ClipboardImagePath = string.Empty;
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using CefSharp;
|
using System;
|
||||||
using System;
|
using CefSharp;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDuck.Core.Handling.General{
|
||||||
class BrowserProcessHandler : IBrowserProcessHandler{
|
class BrowserProcessHandler : IBrowserProcessHandler{
|
||||||
void IBrowserProcessHandler.OnContextInitialized(){
|
void IBrowserProcessHandler.OnContextInitialized(){
|
||||||
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
|
using(IRequestContext ctx = Cef.GetGlobalRequestContext()){
|
||||||
string err;
|
ctx.SetPreference("browser.enable_spellchecking", Program.UserConfig.EnableSpellCheck, out string _);
|
||||||
ctx.SetPreference("browser.enable_spellchecking", Program.UserConfig.EnableSpellCheck, out err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
70
Core/Handling/General/JavaScriptDialogHandler.cs
Normal file
70
Core/Handling/General/JavaScriptDialogHandler.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
|
using CefSharp.WinForms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling.General{
|
||||||
|
class JavaScriptDialogHandler : IJsDialogHandler{
|
||||||
|
bool IJsDialogHandler.OnJSDialog(IWebBrowser browserControl, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage){
|
||||||
|
((ChromiumWebBrowser)browserControl).InvokeSafe(() => {
|
||||||
|
FormMessage form;
|
||||||
|
TextBox input = null;
|
||||||
|
|
||||||
|
if (dialogType == CefJsDialogType.Alert){
|
||||||
|
form = new FormMessage("Browser Message", messageText, MessageBoxIcon.None);
|
||||||
|
form.AddButton(FormMessage.OK, ControlType.Accept | ControlType.Focused);
|
||||||
|
}
|
||||||
|
else if (dialogType == CefJsDialogType.Confirm){
|
||||||
|
form = new FormMessage("Browser Confirmation", messageText, MessageBoxIcon.None);
|
||||||
|
form.AddButton(FormMessage.No, DialogResult.No, ControlType.Cancel);
|
||||||
|
form.AddButton(FormMessage.Yes, ControlType.Focused);
|
||||||
|
}
|
||||||
|
else if (dialogType == CefJsDialogType.Prompt){
|
||||||
|
form = new FormMessage("Browser Prompt", messageText, MessageBoxIcon.None);
|
||||||
|
form.AddButton(FormMessage.Cancel, DialogResult.Cancel, ControlType.Cancel);
|
||||||
|
form.AddButton(FormMessage.OK, ControlType.Accept | ControlType.Focused);
|
||||||
|
|
||||||
|
float dpiScale = form.GetDPIScale();
|
||||||
|
|
||||||
|
input = new TextBox{
|
||||||
|
Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom,
|
||||||
|
Location = new Point(BrowserUtils.Scale(22, dpiScale), form.ActionPanelY-BrowserUtils.Scale(46, dpiScale)),
|
||||||
|
Size = new Size(form.ClientSize.Width-BrowserUtils.Scale(44, dpiScale), 20)
|
||||||
|
};
|
||||||
|
|
||||||
|
form.Controls.Add(input);
|
||||||
|
form.ActiveControl = input;
|
||||||
|
form.Height += input.Size.Height+input.Margin.Vertical;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
callback.Continue(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = form.ShowDialog() == DialogResult.OK;
|
||||||
|
|
||||||
|
if (input == null){
|
||||||
|
callback.Continue(success);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
callback.Continue(success, input.Text);
|
||||||
|
input.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
form.Dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IJsDialogHandler.OnJSBeforeUnload(IWebBrowser browserControl, IBrowser browser, string message, bool isReload, IJsDialogCallback callback){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IJsDialogHandler.OnResetDialogState(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
void IJsDialogHandler.OnDialogClosed(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
namespace TweetDuck.Core.Handling.General{
|
||||||
class LifeSpanHandler : ILifeSpanHandler{
|
class LifeSpanHandler : ILifeSpanHandler{
|
||||||
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser){
|
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser){
|
||||||
newBrowser = null;
|
newBrowser = null;
|
||||||
68
Core/Handling/General/RequestHandlerBase.cs
Normal file
68
Core/Handling/General/RequestHandlerBase.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using CefSharp;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling.General{
|
||||||
|
abstract class RequestHandlerBase : IRequestHandler{
|
||||||
|
// Browser
|
||||||
|
|
||||||
|
public virtual void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser){}
|
||||||
|
|
||||||
|
public virtual void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){}
|
||||||
|
|
||||||
|
public virtual bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
|
||||||
|
public virtual CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){
|
||||||
|
return CefReturnValue.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl){}
|
||||||
|
|
||||||
|
public virtual bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength){}
|
||||||
|
|
||||||
|
// JavaScript & Plugins
|
||||||
|
|
||||||
|
public virtual bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath){}
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
|
||||||
|
public virtual bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Core/Handling/KeyboardHandlerBrowser.cs
Normal file
24
Core/Handling/KeyboardHandlerBrowser.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling{
|
||||||
|
sealed class KeyboardHandlerBrowser : IKeyboardHandler{
|
||||||
|
private readonly FormBrowser form;
|
||||||
|
|
||||||
|
public KeyboardHandlerBrowser(FormBrowser form){
|
||||||
|
this.form = form;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKeyboardHandler.OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut){
|
||||||
|
if (type == KeyType.RawKeyDown && (Keys)windowsKeyCode == Keys.Space){
|
||||||
|
return form.ToggleVideoPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKeyboardHandler.OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
Core/Handling/KeyboardHandlerNotification.cs
Normal file
38
Core/Handling/KeyboardHandlerNotification.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Notification;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling {
|
||||||
|
sealed class KeyboardHandlerNotification : IKeyboardHandler{
|
||||||
|
private readonly FormNotificationBase notification;
|
||||||
|
|
||||||
|
public KeyboardHandlerNotification(FormNotificationBase notification){
|
||||||
|
this.notification = notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKeyboardHandler.OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut){
|
||||||
|
if (type == KeyType.RawKeyDown && !browser.FocusedFrame.Url.StartsWith("chrome-devtools://")){
|
||||||
|
switch((Keys)windowsKeyCode){
|
||||||
|
case Keys.Enter:
|
||||||
|
notification.InvokeAsyncSafe(notification.FinishCurrentNotification);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case Keys.Escape:
|
||||||
|
notification.InvokeAsyncSafe(() => notification.HideNotification(true));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case Keys.Space:
|
||||||
|
notification.InvokeAsyncSafe(() => notification.FreezeTimer = !notification.FreezeTimer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKeyboardHandler.OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Core/Handling/RequestHandlerBrowser.cs
Normal file
18
Core/Handling/RequestHandlerBrowser.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using TweetDuck.Core.Handling.General;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling{
|
||||||
|
class RequestHandlerBrowser : RequestHandlerBase{
|
||||||
|
public override void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status){
|
||||||
|
browser.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback){
|
||||||
|
if (request.ResourceType == ResourceType.Script && request.Url.Contains("analytics.")){
|
||||||
|
return CefReturnValue.Cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CefReturnValue.Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Core/Handling/ResourceHandlerNotification.cs
Normal file
63
Core/Handling/ResourceHandlerNotification.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Handling{
|
||||||
|
class ResourceHandlerNotification : IResourceHandler{
|
||||||
|
private readonly NameValueCollection headers = new NameValueCollection(0);
|
||||||
|
private MemoryStream dataIn;
|
||||||
|
|
||||||
|
public void SetHTML(string html){
|
||||||
|
dataIn?.Dispose();
|
||||||
|
dataIn = ResourceHandler.GetMemoryStream(html, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
if (dataIn != null){
|
||||||
|
dataIn.Dispose();
|
||||||
|
dataIn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.ProcessRequest(IRequest request, ICallback callback){
|
||||||
|
callback.Continue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceHandler.GetResponseHeaders(IResponse response, out long responseLength, out string redirectUrl){
|
||||||
|
redirectUrl = null;
|
||||||
|
|
||||||
|
response.MimeType = "text/html";
|
||||||
|
response.StatusCode = 200;
|
||||||
|
response.StatusText = "OK";
|
||||||
|
response.ResponseHeaders = headers;
|
||||||
|
responseLength = dataIn?.Length ?? -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.ReadResponse(Stream dataOut, out int bytesRead, ICallback callback){
|
||||||
|
callback.Dispose();
|
||||||
|
|
||||||
|
try{
|
||||||
|
int length = (int)dataIn.Length;
|
||||||
|
|
||||||
|
dataIn.CopyTo(dataOut, length);
|
||||||
|
bytesRead = length;
|
||||||
|
return true;
|
||||||
|
}catch{ // catch IOException, possibly NullReferenceException if dataIn is null
|
||||||
|
bytesRead = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.CanGetCookie(Cookie cookie){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceHandler.CanSetCookie(Cookie cookie){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceHandler.Cancel(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDck.Core.Utils;
|
|
||||||
using TweetDck.Core.Controls;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
|
||||||
class TweetDeckBridge{
|
|
||||||
public static string LastRightClickedLink = string.Empty;
|
|
||||||
public static string LastHighlightedTweet = string.Empty;
|
|
||||||
public static string LastHighlightedQuotedTweet = string.Empty;
|
|
||||||
public static string NotificationTweetEmbedded = string.Empty;
|
|
||||||
public static string ClipboardImagePath = string.Empty;
|
|
||||||
|
|
||||||
private readonly FormBrowser form;
|
|
||||||
private readonly FormNotification notification;
|
|
||||||
|
|
||||||
public string BrandName{
|
|
||||||
get{
|
|
||||||
return Program.BrandName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string VersionTag{
|
|
||||||
get{
|
|
||||||
return Program.VersionTag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MuteNotifications{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.MuteNotifications;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ExpandLinksOnHover{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.ExpandLinksOnHover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasCustomBrowserCSS{
|
|
||||||
get{
|
|
||||||
return !string.IsNullOrEmpty(Program.UserConfig.CustomBrowserCSS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string CustomBrowserCSS{
|
|
||||||
get{
|
|
||||||
return Program.UserConfig.CustomBrowserCSS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TweetDeckBridge(FormBrowser form, FormNotification notification){
|
|
||||||
this.form = form;
|
|
||||||
this.notification = notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadFontSizeClass(string fsClass){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
TweetNotification.SetFontSizeClass(fsClass);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadNotificationHeadContents(string headContents){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
TweetNotification.SetHeadTag(headContents);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetLastRightClickedLink(string link){
|
|
||||||
form.InvokeSafe(() => LastRightClickedLink = link);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetLastHighlightedTweet(string link, string quotedLink){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
LastHighlightedTweet = link;
|
|
||||||
LastHighlightedQuotedTweet = quotedLink;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetNotificationTweetEmbedded(string link){
|
|
||||||
form.InvokeSafe(() => NotificationTweetEmbedded = link);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenSettingsMenu(){
|
|
||||||
form.InvokeSafe(form.OpenSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenPluginsMenu(){
|
|
||||||
form.InvokeSafe(form.OpenPlugins);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetPopup(string tweetHtml, string tweetUrl, int tweetCharacters){
|
|
||||||
notification.InvokeSafe(() => {
|
|
||||||
form.OnTweetNotification();
|
|
||||||
notification.ShowNotification(new TweetNotification(tweetHtml, tweetUrl, tweetCharacters));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnTweetSound(){
|
|
||||||
form.InvokeSafe(form.OnTweetNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnNotificationReady(){
|
|
||||||
if (!Program.UserConfig.NotificationLegacyLoad){
|
|
||||||
notification.InvokeSafe(notification.OnNotificationReady);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DisplayTooltip(string text, bool showInNotification){
|
|
||||||
if (showInNotification){
|
|
||||||
notification.InvokeSafe(() => notification.DisplayTooltip(text));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
form.InvokeSafe(() => form.DisplayTooltip(text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadNextNotification(){
|
|
||||||
notification.InvokeSafe(notification.FinishCurrentTweet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TryPasteImage(){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
if (Clipboard.ContainsImage()){
|
|
||||||
Image img = Clipboard.GetImage();
|
|
||||||
if (img == null)return;
|
|
||||||
|
|
||||||
try{
|
|
||||||
Directory.CreateDirectory(Program.TemporaryPath);
|
|
||||||
|
|
||||||
ClipboardImagePath = Path.Combine(Program.TemporaryPath, "TD-Img-"+DateTime.Now.Ticks+".png");
|
|
||||||
img.Save(ClipboardImagePath, ImageFormat.Png);
|
|
||||||
|
|
||||||
form.OnImagePasted();
|
|
||||||
}catch(Exception e){
|
|
||||||
Program.Reporter.HandleException("Clipboard Image Error", "Could not paste image from clipboard.", true, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClickUploadImage(int offsetX, int offsetY){
|
|
||||||
form.InvokeSafe(() => {
|
|
||||||
Point prevPos = Cursor.Position;
|
|
||||||
|
|
||||||
Cursor.Position = form.PointToScreen(new Point(offsetX, offsetY));
|
|
||||||
NativeMethods.SimulateMouseClick(NativeMethods.MouseButton.Left);
|
|
||||||
Cursor.Position = prevPos;
|
|
||||||
|
|
||||||
form.OnImagePastedFinish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenBrowser(string url){
|
|
||||||
BrowserUtils.OpenExternalBrowser(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Alert(string type, string contents){
|
|
||||||
MessageBoxIcon icon;
|
|
||||||
|
|
||||||
switch(type){
|
|
||||||
case "error": icon = MessageBoxIcon.Error; break;
|
|
||||||
case "warning": icon = MessageBoxIcon.Warning; break;
|
|
||||||
case "info": icon = MessageBoxIcon.Information; break;
|
|
||||||
default: icon = MessageBoxIcon.None; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBox.Show(contents, Program.BrandName+" Browser Message", MessageBoxButtons.OK, icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string data){
|
|
||||||
System.Diagnostics.Debug.WriteLine(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Handling{
|
|
||||||
sealed class TweetNotification{
|
|
||||||
private static string FontSizeClass { get; set; }
|
|
||||||
private static string HeadTag { get; set; }
|
|
||||||
|
|
||||||
private static string DefaultFontSizeClass{
|
|
||||||
get{
|
|
||||||
return "medium";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string DefaultHeadTag{
|
|
||||||
get{
|
|
||||||
return @"<meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='chrome=1'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/font.5ef884f9f9.css'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/app-dark.5631e0dd42.css'>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CustomCSS{
|
|
||||||
get{
|
|
||||||
return @".scroll-styled-v::-webkit-scrollbar{width:8px}.scroll-styled-v::-webkit-scrollbar-thumb{border-radius:0}a[data-full-url]{word-break:break-all}#td-skip{opacity:0;cursor:pointer;transition:opacity 0.15s ease}.td-hover #td-skip{opacity:0.75}#td-skip:hover{opacity:1}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int FontSizeLevel{
|
|
||||||
get{
|
|
||||||
switch(FontSizeClass){
|
|
||||||
case "largest": return 4;
|
|
||||||
case "large": return 3;
|
|
||||||
case "medium": return 2;
|
|
||||||
case "small": return 1;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TweetNotification ExampleTweet{
|
|
||||||
get{
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
build.Append(@"<article><div class='js-stream-item-content item-box js-show-detail'><div class='js-tweet tweet'>");
|
|
||||||
build.Append(@"<header class='tweet-header'>");
|
|
||||||
build.Append(@"<time class='tweet-timestamp js-timestamp pull-right txt-mute'><a target='_blank' rel='url' href='https://twitter.com/chylexmc' class='txt-small'>0s</a></time>");
|
|
||||||
build.Append(@"<a target='_blank' rel='user' href='https://twitter.com/chylexmc' class='account-link link-complex block'>");
|
|
||||||
build.Append(@"<div class='obj-left item-img tweet-img'><img width='48' height='48' alt='chylexmc's avatar' src='https://pbs.twimg.com/profile_images/765161905312980992/AhDP9iY-_normal.jpg' class='tweet-avatar avatar pull-right'></div>");
|
|
||||||
build.Append(@"<div class='nbfc'><span class='account-inline txt-ellipsis'><b class='fullname link-complex-target'>chylex</b> <span class='username txt-mute'>@chylexmc</span></span></div>");
|
|
||||||
build.Append(@"</a>");
|
|
||||||
build.Append(@"</header>");
|
|
||||||
build.Append(@"<div class='tweet-body'><p class='js-tweet-text tweet-text with-linebreaks'>This is an example tweet, which lets you test the location and duration of popup notifications.</p></div>");
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
build.Append(@"<div style='margin-top:64px'>Scrollbar test padding...</div>");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
build.Append(@"</div></div></article>");
|
|
||||||
|
|
||||||
return new TweetNotification(build.ToString(), "", 95, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFontSizeClass(string newFSClass){
|
|
||||||
FontSizeClass = newFSClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetHeadTag(string headContents){
|
|
||||||
HeadTag = headContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Position{
|
|
||||||
TopLeft, TopRight, BottomLeft, BottomRight, Custom
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Duration{
|
|
||||||
Short, Medium, Long, VeryLong
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Url{
|
|
||||||
get{
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly string html;
|
|
||||||
private readonly string url;
|
|
||||||
private readonly int characters;
|
|
||||||
private readonly bool isExample;
|
|
||||||
|
|
||||||
public TweetNotification(string html, string url, int characters) : this(html, url, characters, false){}
|
|
||||||
|
|
||||||
private TweetNotification(string html, string url, int characters, bool isExample){
|
|
||||||
this.html = html;
|
|
||||||
this.url = url;
|
|
||||||
this.characters = characters;
|
|
||||||
this.isExample = isExample;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetDisplayDuration(int value){
|
|
||||||
return 2000+Math.Max(1000, value*characters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateHtml(){
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
build.Append("<!DOCTYPE html>");
|
|
||||||
build.Append("<html class='os-windows txt-base-").Append(FontSizeClass ?? DefaultFontSizeClass).Append("'>");
|
|
||||||
build.Append("<head>").Append(HeadTag ?? DefaultHeadTag).Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
|
|
||||||
build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
|
|
||||||
}
|
|
||||||
|
|
||||||
build.Append("</head>");
|
|
||||||
build.Append("<body class='hearty'").Append(isExample ? " td-example-notification" : "").Append("><div class='app-columns-container'><div class='column scroll-styled-v' style='width:100%;overflow-y:auto'>");
|
|
||||||
build.Append(html);
|
|
||||||
build.Append("</div></div></body>");
|
|
||||||
build.Append("</html>");
|
|
||||||
return build.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
Core/Notification/FormNotificationBase.Designer.cs
generated
Normal file
52
Core/Notification/FormNotificationBase.Designer.cs
generated
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
namespace TweetDuck.Core.Notification {
|
||||||
|
partial class FormNotificationBase {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// FormNotification
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.BackColor = System.Drawing.SystemColors.Control;
|
||||||
|
this.ClientSize = new System.Drawing.Size(284, 122);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||||
|
this.Location = TweetDuck.Core.Controls.ControlExtensions.InvisibleLocation;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "FormNotification";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
}
|
||||||
|
}
|
||||||
233
Core/Notification/FormNotificationBase.cs
Normal file
233
Core/Notification/FormNotificationBase.cs
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using CefSharp.WinForms;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Configuration;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Handling;
|
||||||
|
using TweetDuck.Core.Handling.General;
|
||||||
|
using TweetDuck.Core.Other.Management;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification{
|
||||||
|
partial class FormNotificationBase : Form{
|
||||||
|
protected Point PrimaryLocation{
|
||||||
|
get{
|
||||||
|
UserConfig config = Program.UserConfig;
|
||||||
|
Screen screen;
|
||||||
|
|
||||||
|
if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
|
||||||
|
screen = Screen.AllScreens[config.NotificationDisplay-1];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
screen = Screen.FromControl(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
int edgeDist = config.NotificationEdgeDistance;
|
||||||
|
|
||||||
|
switch(config.NotificationPosition){
|
||||||
|
case TweetNotification.Position.TopLeft:
|
||||||
|
return new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+edgeDist);
|
||||||
|
|
||||||
|
case TweetNotification.Position.TopRight:
|
||||||
|
return new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
||||||
|
|
||||||
|
case TweetNotification.Position.BottomLeft:
|
||||||
|
return new Point(screen.WorkingArea.X+edgeDist, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
||||||
|
|
||||||
|
case TweetNotification.Position.BottomRight:
|
||||||
|
return new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+screen.WorkingArea.Height-edgeDist-Height);
|
||||||
|
|
||||||
|
case TweetNotification.Position.Custom:
|
||||||
|
if (!config.IsCustomNotificationPositionSet){
|
||||||
|
config.CustomNotificationPosition = new Point(screen.WorkingArea.X+screen.WorkingArea.Width-edgeDist-Width, screen.WorkingArea.Y+edgeDist);
|
||||||
|
config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.CustomNotificationPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsNotificationVisible => Location != ControlExtensions.InvisibleLocation;
|
||||||
|
|
||||||
|
public new Point Location{
|
||||||
|
get => base.Location;
|
||||||
|
|
||||||
|
set{
|
||||||
|
Visible = (base.Location = value) != ControlExtensions.InvisibleLocation;
|
||||||
|
FormBorderStyle = GetBorderStyle(CanResizeWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanResizeWindow{
|
||||||
|
get => FormBorderStyle == FormBorderStyle.Sizable || FormBorderStyle == FormBorderStyle.SizableToolWindow;
|
||||||
|
set => FormBorderStyle = GetBorderStyle(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<bool> CanMoveWindow { get; set; } = () => true;
|
||||||
|
protected override bool ShowWithoutActivation => true;
|
||||||
|
|
||||||
|
protected double SizeScale => dpiScale*Program.UserConfig.ZoomMultiplier;
|
||||||
|
|
||||||
|
protected readonly Form owner;
|
||||||
|
protected readonly ChromiumWebBrowser browser;
|
||||||
|
|
||||||
|
private readonly ResourceHandlerNotification resourceHandler = new ResourceHandlerNotification();
|
||||||
|
private readonly float dpiScale;
|
||||||
|
|
||||||
|
private string currentColumn;
|
||||||
|
private int pauseCounter;
|
||||||
|
|
||||||
|
public bool IsPaused => pauseCounter > 0;
|
||||||
|
|
||||||
|
public bool FreezeTimer { get; set; }
|
||||||
|
public bool ContextMenuOpen { get; set; }
|
||||||
|
public string CurrentTweetUrl { get; private set; }
|
||||||
|
public string CurrentQuoteUrl { get; private set; }
|
||||||
|
|
||||||
|
public event EventHandler Initialized;
|
||||||
|
|
||||||
|
public FormNotificationBase(Form owner, bool enableContextMenu){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.owner = owner;
|
||||||
|
this.owner.FormClosed += owner_FormClosed;
|
||||||
|
|
||||||
|
this.browser = new ChromiumWebBrowser("about:blank"){
|
||||||
|
MenuHandler = new ContextMenuNotification(this, enableContextMenu),
|
||||||
|
JsDialogHandler = new JavaScriptDialogHandler(),
|
||||||
|
LifeSpanHandler = new LifeSpanHandler()
|
||||||
|
};
|
||||||
|
|
||||||
|
this.browser.Dock = DockStyle.None;
|
||||||
|
this.browser.ClientSize = ClientSize;
|
||||||
|
this.browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
this.browser.ConsoleMessage += BrowserUtils.HandleConsoleMessage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this.dpiScale = this.GetDPIScale();
|
||||||
|
|
||||||
|
DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
|
||||||
|
handlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
|
||||||
|
|
||||||
|
Controls.Add(browser);
|
||||||
|
|
||||||
|
Disposed += (sender, args) => {
|
||||||
|
this.browser.Dispose();
|
||||||
|
this.owner.FormClosed -= owner_FormClosed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ReSharper disable once VirtualMemberCallInContructor
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WndProc(ref Message m){
|
||||||
|
if (m.Msg == 0x0112 && (m.WParam.ToInt32() & 0xFFF0) == 0xF010 && !CanMoveWindow()){ // WM_SYSCOMMAND, SC_MOVE
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void owner_FormClosed(object sender, FormClosedEventArgs e){
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e){
|
||||||
|
if (e.IsBrowserInitialized){
|
||||||
|
Initialized?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
|
int identifier = browser.GetBrowser().Identifier;
|
||||||
|
Disposed += (sender2, args2) => BrowserProcesses.Forget(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public virtual void HideNotification(bool loadBlank){
|
||||||
|
if (loadBlank){
|
||||||
|
browser.Load("about:blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
Location = ControlExtensions.InvisibleLocation;
|
||||||
|
currentColumn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void FinishCurrentNotification(){}
|
||||||
|
|
||||||
|
public virtual void PauseNotification(){
|
||||||
|
if (pauseCounter++ == 0 && IsNotificationVisible){
|
||||||
|
Location = ControlExtensions.InvisibleLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ResumeNotification(){
|
||||||
|
if (pauseCounter > 0){
|
||||||
|
--pauseCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string GetTweetHTML(TweetNotification tweet){
|
||||||
|
string bodyClasses = browser.Bounds.Contains(PointToClient(Cursor.Position)) ? "td-hover" : string.Empty;
|
||||||
|
return tweet.GenerateHtml(bodyClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void LoadTweet(TweetNotification tweet){
|
||||||
|
CurrentTweetUrl = tweet.TweetUrl;
|
||||||
|
CurrentQuoteUrl = tweet.QuoteUrl;
|
||||||
|
currentColumn = tweet.Column;
|
||||||
|
|
||||||
|
resourceHandler.SetHTML(GetTweetHTML(tweet));
|
||||||
|
browser.Load(TwitterUtils.TweetDeckURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetNotificationSize(int width, int height){
|
||||||
|
browser.ClientSize = ClientSize = new Size(BrowserUtils.Scale(width, SizeScale), BrowserUtils.Scale(height, SizeScale));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnNotificationReady(){
|
||||||
|
MoveToVisibleLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateTitle(){
|
||||||
|
Text = string.IsNullOrEmpty(currentColumn) || !Program.UserConfig.DisplayNotificationColumn ? Program.BrandName : Program.BrandName+" - "+currentColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveToVisibleLocation(){
|
||||||
|
bool needsReactivating = Location == ControlExtensions.InvisibleLocation;
|
||||||
|
Location = PrimaryLocation;
|
||||||
|
|
||||||
|
if (needsReactivating){
|
||||||
|
NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisplayTooltip(string text){
|
||||||
|
if (string.IsNullOrEmpty(text)){
|
||||||
|
toolTip.Hide(this);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Point position = PointToClient(Cursor.Position);
|
||||||
|
position.Offset(20, 5);
|
||||||
|
toolTip.Show(text, this, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FormBorderStyle GetBorderStyle(bool sizable){
|
||||||
|
if (WindowsUtils.ShouldAvoidToolWindow && Visible){ // Visible = workaround for alt+tab
|
||||||
|
return sizable ? FormBorderStyle.Sizable : FormBorderStyle.FixedSingle;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return sizable ? FormBorderStyle.SizableToolWindow : FormBorderStyle.FixedToolWindow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
using TweetDck.Core.Controls;
|
namespace TweetDuck.Core.Notification {
|
||||||
|
partial class FormNotificationMain {
|
||||||
namespace TweetDck.Core {
|
|
||||||
sealed partial class FormNotification {
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -26,22 +24,15 @@ namespace TweetDck.Core {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.panelBrowser = new System.Windows.Forms.Panel();
|
this.timerDisplayDelay = new System.Windows.Forms.Timer(this.components);
|
||||||
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
this.timerProgress = new System.Windows.Forms.Timer(this.components);
|
||||||
this.progressBarTimer = new TweetDck.Core.Controls.FlatProgressBar();
|
this.progressBarTimer = new TweetDuck.Core.Controls.FlatProgressBar();
|
||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// panelBrowser
|
// timerDisplayDelay
|
||||||
//
|
//
|
||||||
this.panelBrowser.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.timerDisplayDelay.Interval = 17;
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
this.timerDisplayDelay.Tick += new System.EventHandler(this.timerDisplayDelay_Tick);
|
||||||
this.panelBrowser.BackColor = System.Drawing.Color.White;
|
|
||||||
this.panelBrowser.Location = new System.Drawing.Point(0, 0);
|
|
||||||
this.panelBrowser.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.panelBrowser.Name = "panelBrowser";
|
|
||||||
this.panelBrowser.Size = new System.Drawing.Size(284, 118);
|
|
||||||
this.panelBrowser.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// timerProgress
|
// timerProgress
|
||||||
//
|
//
|
||||||
@@ -58,7 +49,7 @@ namespace TweetDck.Core {
|
|||||||
this.progressBarTimer.Margin = new System.Windows.Forms.Padding(0);
|
this.progressBarTimer.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.progressBarTimer.Maximum = 1000;
|
this.progressBarTimer.Maximum = 1000;
|
||||||
this.progressBarTimer.Name = "progressBarTimer";
|
this.progressBarTimer.Name = "progressBarTimer";
|
||||||
this.progressBarTimer.Size = new System.Drawing.Size(284, 4);
|
this.progressBarTimer.Size = new System.Drawing.Size(284, TimerBarHeight);
|
||||||
this.progressBarTimer.TabIndex = 1;
|
this.progressBarTimer.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// FormNotification
|
// FormNotification
|
||||||
@@ -68,15 +59,6 @@ namespace TweetDck.Core {
|
|||||||
this.BackColor = System.Drawing.SystemColors.Control;
|
this.BackColor = System.Drawing.SystemColors.Control;
|
||||||
this.ClientSize = new System.Drawing.Size(284, 122);
|
this.ClientSize = new System.Drawing.Size(284, 122);
|
||||||
this.Controls.Add(this.progressBarTimer);
|
this.Controls.Add(this.progressBarTimer);
|
||||||
this.Controls.Add(this.panelBrowser);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
|
||||||
this.Location = new System.Drawing.Point(-32000, -32000);
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.MinimizeBox = false;
|
|
||||||
this.Name = "FormNotification";
|
|
||||||
this.ShowIcon = false;
|
|
||||||
this.ShowInTaskbar = false;
|
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotification_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotification_FormClosing);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
@@ -84,9 +66,8 @@ namespace TweetDck.Core {
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Panel panelBrowser;
|
private System.Windows.Forms.Timer timerDisplayDelay;
|
||||||
|
protected System.Windows.Forms.Timer timerProgress;
|
||||||
private Controls.FlatProgressBar progressBarTimer;
|
private Controls.FlatProgressBar progressBarTimer;
|
||||||
private System.Windows.Forms.Timer timerProgress;
|
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
287
Core/Notification/FormNotificationMain.cs
Normal file
287
Core/Notification/FormNotificationMain.cs
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Bridge;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Handling;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using TweetDuck.Plugins.Enums;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification{
|
||||||
|
partial class FormNotificationMain : FormNotificationBase{
|
||||||
|
private const string NotificationScriptFile = "notification.js";
|
||||||
|
private const int TimerBarHeight = 4;
|
||||||
|
|
||||||
|
private static readonly string NotificationScriptIdentifier = ScriptLoader.GetRootIdentifier(NotificationScriptFile);
|
||||||
|
private static readonly string NotificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
|
||||||
|
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
|
protected int timeLeft, totalTime;
|
||||||
|
protected bool pausedDuringNotification;
|
||||||
|
|
||||||
|
private readonly NativeMethods.HookProc mouseHookDelegate;
|
||||||
|
private IntPtr mouseHook;
|
||||||
|
private bool blockXButtonUp;
|
||||||
|
|
||||||
|
private bool? prevDisplayTimer;
|
||||||
|
private int? prevFontSize;
|
||||||
|
|
||||||
|
public bool RequiresResize{
|
||||||
|
get{
|
||||||
|
return !prevDisplayTimer.HasValue || !prevFontSize.HasValue || prevDisplayTimer != Program.UserConfig.DisplayNotificationTimer || prevFontSize != TweetNotification.FontSizeLevel || CanResizeWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
set{
|
||||||
|
if (value){
|
||||||
|
prevDisplayTimer = null;
|
||||||
|
prevFontSize = null;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
prevDisplayTimer = Program.UserConfig.DisplayNotificationTimer;
|
||||||
|
prevFontSize = TweetNotification.FontSizeLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int BaseClientWidth{
|
||||||
|
get{
|
||||||
|
switch(Program.UserConfig.NotificationSize){
|
||||||
|
default:
|
||||||
|
return BrowserUtils.Scale(284, SizeScale*(1.0+0.05*TweetNotification.FontSizeLevel));
|
||||||
|
|
||||||
|
case TweetNotification.Size.Custom:
|
||||||
|
return Program.UserConfig.CustomNotificationSize.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int BaseClientHeight{
|
||||||
|
get{
|
||||||
|
switch(Program.UserConfig.NotificationSize){
|
||||||
|
default:
|
||||||
|
return BrowserUtils.Scale(122, SizeScale*(1.0+0.075*TweetNotification.FontSizeLevel));
|
||||||
|
|
||||||
|
case TweetNotification.Size.Custom:
|
||||||
|
return Program.UserConfig.CustomNotificationSize.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size BrowserSize{
|
||||||
|
get => Program.UserConfig.DisplayNotificationTimer ? new Size(ClientSize.Width, ClientSize.Height-TimerBarHeight) : ClientSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormNotificationMain(FormBrowser owner, PluginManager pluginManager, bool enableContextMenu) : base(owner, enableContextMenu){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.plugins = pluginManager;
|
||||||
|
|
||||||
|
browser.KeyboardHandler = new KeyboardHandlerNotification(this);
|
||||||
|
|
||||||
|
browser.RegisterAsyncJsObject("$TD", new TweetDeckBridge(owner, this));
|
||||||
|
browser.RegisterAsyncJsObject("$TDP", plugins.Bridge);
|
||||||
|
|
||||||
|
browser.LoadingStateChanged += Browser_LoadingStateChanged;
|
||||||
|
browser.FrameLoadEnd += Browser_FrameLoadEnd;
|
||||||
|
|
||||||
|
mouseHookDelegate = MouseHookProc;
|
||||||
|
Disposed += (sender, args) => StopMouseHook(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mouse wheel hook
|
||||||
|
|
||||||
|
private void StartMouseHook(){
|
||||||
|
if (mouseHook == IntPtr.Zero){
|
||||||
|
mouseHook = NativeMethods.SetWindowsHookEx(NativeMethods.WM_MOUSE_LL, mouseHookDelegate, IntPtr.Zero, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopMouseHook(bool force){
|
||||||
|
if (mouseHook != IntPtr.Zero && (force || !blockXButtonUp)){
|
||||||
|
NativeMethods.UnhookWindowsHookEx(mouseHook);
|
||||||
|
mouseHook = IntPtr.Zero;
|
||||||
|
blockXButtonUp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam){
|
||||||
|
if (nCode == 0){
|
||||||
|
int eventType = wParam.ToInt32();
|
||||||
|
|
||||||
|
if (eventType == NativeMethods.WM_MOUSEWHEEL && browser.Bounds.Contains(PointToClient(Cursor.Position))){
|
||||||
|
browser.SendMouseWheelEvent(0, 0, 0, BrowserUtils.Scale(NativeMethods.GetMouseHookData(lParam), Program.UserConfig.NotificationScrollSpeed/100.0), CefEventFlags.None);
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
else if (eventType == NativeMethods.WM_XBUTTONDOWN && DesktopBounds.Contains(Cursor.Position)){
|
||||||
|
int extraButton = NativeMethods.GetMouseHookData(lParam);
|
||||||
|
|
||||||
|
if (extraButton == 2){ // forward button
|
||||||
|
this.InvokeAsyncSafe(FinishCurrentNotification);
|
||||||
|
}
|
||||||
|
else if (extraButton == 1){ // back button
|
||||||
|
this.InvokeAsyncSafe(Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockXButtonUp = true;
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
else if (eventType == NativeMethods.WM_XBUTTONUP && blockXButtonUp){
|
||||||
|
blockXButtonUp = false;
|
||||||
|
|
||||||
|
if (!Visible){
|
||||||
|
StopMouseHook(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NativeMethods.HOOK_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NativeMethods.CallNextHookEx(mouseHook, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void FormNotification_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (e.CloseReason == CloseReason.UserClosing){
|
||||||
|
HideNotification(true);
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
|
||||||
|
if (!e.IsLoading && browser.Address != "about:blank"){
|
||||||
|
this.InvokeSafe(() => {
|
||||||
|
Visible = true; // ensures repaint before moving the window to a visible location
|
||||||
|
timerDisplayDelay.Start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
|
||||||
|
if (e.Frame.IsMain && NotificationJS != null && browser.Address != "about:blank"){
|
||||||
|
e.Frame.ExecuteJavaScriptAsync(PropertyBridge.GenerateScript(PropertyBridge.Environment.Notification));
|
||||||
|
ScriptLoader.ExecuteScript(e.Frame, NotificationJS, NotificationScriptIdentifier);
|
||||||
|
plugins.ExecutePlugins(e.Frame, PluginEnvironment.Notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerDisplayDelay_Tick(object sender, EventArgs e){
|
||||||
|
OnNotificationReady();
|
||||||
|
timerDisplayDelay.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerHideProgress_Tick(object sender, EventArgs e){
|
||||||
|
if (Bounds.Contains(Cursor.Position) || FreezeTimer || ContextMenuOpen)return;
|
||||||
|
|
||||||
|
timeLeft -= timerProgress.Interval;
|
||||||
|
|
||||||
|
int value = BrowserUtils.Scale(1025, (totalTime-timeLeft)/(double)totalTime);
|
||||||
|
progressBarTimer.SetValueInstant(Math.Min(1000, Math.Max(0, Program.UserConfig.NotificationTimerCountDown ? 1000-value : value)));
|
||||||
|
|
||||||
|
if (timeLeft <= 0){
|
||||||
|
FinishCurrentNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public virtual void ShowNotification(TweetNotification notification){
|
||||||
|
LoadTweet(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowNotificationForSettings(bool reset){
|
||||||
|
if (reset){
|
||||||
|
LoadTweet(TweetNotification.ExampleTweet);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
PrepareAndDisplayWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HideNotification(bool loadBlank){
|
||||||
|
base.HideNotification(loadBlank);
|
||||||
|
|
||||||
|
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
||||||
|
timerProgress.Stop();
|
||||||
|
totalTime = 0;
|
||||||
|
|
||||||
|
StopMouseHook(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FinishCurrentNotification(){
|
||||||
|
timerProgress.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PauseNotification(){
|
||||||
|
if (!IsPaused){
|
||||||
|
pausedDuringNotification = IsNotificationVisible;
|
||||||
|
timerProgress.Stop();
|
||||||
|
StopMouseHook(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.PauseNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResumeNotification(){
|
||||||
|
bool wasPaused = IsPaused;
|
||||||
|
base.ResumeNotification();
|
||||||
|
|
||||||
|
if (wasPaused && !IsPaused && pausedDuringNotification){
|
||||||
|
OnNotificationReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTweetHTML(TweetNotification tweet){
|
||||||
|
string html = base.GetTweetHTML(tweet);
|
||||||
|
|
||||||
|
foreach(InjectedHTML injection in plugins.Bridge.NotificationInjections){
|
||||||
|
html = injection.Inject(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadTweet(TweetNotification tweet){
|
||||||
|
timerProgress.Stop();
|
||||||
|
totalTime = timeLeft = tweet.GetDisplayDuration(Program.UserConfig.NotificationDurationValue);
|
||||||
|
progressBarTimer.Value = Program.UserConfig.NotificationTimerCountDown ? 1000 : 0;
|
||||||
|
|
||||||
|
base.LoadTweet(tweet);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetNotificationSize(int width, int height){
|
||||||
|
if (Program.UserConfig.DisplayNotificationTimer){
|
||||||
|
ClientSize = new Size(width, height+TimerBarHeight);
|
||||||
|
progressBarTimer.Visible = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ClientSize = new Size(width, height);
|
||||||
|
progressBarTimer.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.ClientSize = new Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareAndDisplayWindow(){
|
||||||
|
if (RequiresResize){
|
||||||
|
RequiresResize = false;
|
||||||
|
SetNotificationSize(BaseClientWidth, BaseClientHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveToVisibleLocation();
|
||||||
|
StartMouseHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNotificationReady(){
|
||||||
|
PrepareAndDisplayWindow();
|
||||||
|
timerProgress.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Core/Notification/FormNotificationTweet.Designer.cs
generated
Normal file
53
Core/Notification/FormNotificationTweet.Designer.cs
generated
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
namespace TweetDuck.Core.Notification {
|
||||||
|
partial class FormNotificationTweet {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.timerCursorCheck = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.timerIdlePauseCheck = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// timerCursorCheck
|
||||||
|
//
|
||||||
|
this.timerCursorCheck.Interval = 200;
|
||||||
|
this.timerCursorCheck.Tick += new System.EventHandler(this.timerCursorCheck_Tick);
|
||||||
|
//
|
||||||
|
// timerIdlePauseCheck
|
||||||
|
//
|
||||||
|
this.timerIdlePauseCheck.Interval = 750;
|
||||||
|
this.timerIdlePauseCheck.Tick += new System.EventHandler(this.timerIdlePauseCheck_Tick);
|
||||||
|
//
|
||||||
|
// FormNotificationTweet
|
||||||
|
//
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormNotificationTweet_FormClosing);
|
||||||
|
this.ResumeLayout(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Timer timerCursorCheck;
|
||||||
|
private System.Windows.Forms.Timer timerIdlePauseCheck;
|
||||||
|
}
|
||||||
|
}
|
||||||
141
Core/Notification/FormNotificationTweet.cs
Normal file
141
Core/Notification/FormNotificationTweet.cs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification{
|
||||||
|
sealed partial class FormNotificationTweet : FormNotificationMain{
|
||||||
|
private const int NonIntrusiveIdleLimit = 30;
|
||||||
|
private const int TrimMinimum = 32;
|
||||||
|
|
||||||
|
private bool IsCursorOverNotificationArea => new Rectangle(PrimaryLocation, Size).Contains(Cursor.Position);
|
||||||
|
|
||||||
|
private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
|
||||||
|
private bool needsTrim;
|
||||||
|
|
||||||
|
public FormNotificationTweet(FormBrowser owner, PluginManager pluginManager) : base(owner, pluginManager, true){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Program.UserConfig.MuteToggled += Config_MuteToggled;
|
||||||
|
Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled;
|
||||||
|
|
||||||
|
if (Program.UserConfig.MuteNotifications){
|
||||||
|
PauseNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormNotificationTweet_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (e.CloseReason == CloseReason.UserClosing){
|
||||||
|
tweetQueue.Clear(); // already canceled
|
||||||
|
TrimQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TrimQueue(){
|
||||||
|
if (needsTrim){
|
||||||
|
tweetQueue.TrimExcess();
|
||||||
|
needsTrim = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
|
||||||
|
private void Config_MuteToggled(object sender, EventArgs e){
|
||||||
|
if (Program.UserConfig.MuteNotifications){
|
||||||
|
PauseNotification();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ResumeNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerCursorCheck_Tick(object sender, EventArgs e){
|
||||||
|
if (!IsCursorOverNotificationArea){
|
||||||
|
ResumeNotification();
|
||||||
|
timerCursorCheck.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerIdlePauseCheck_Tick(object sender, EventArgs e){
|
||||||
|
if (NativeMethods.GetIdleSeconds() < Program.UserConfig.NotificationIdlePauseSeconds){
|
||||||
|
ResumeNotification();
|
||||||
|
timerIdlePauseCheck.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// notification methods
|
||||||
|
|
||||||
|
public override void ShowNotification(TweetNotification notification){
|
||||||
|
if (IsPaused){
|
||||||
|
tweetQueue.Enqueue(notification);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
tweetQueue.Enqueue(notification);
|
||||||
|
UpdateTitle();
|
||||||
|
|
||||||
|
if (totalTime == 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
needsTrim |= tweetQueue.Count >= TrimMinimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FinishCurrentNotification(){
|
||||||
|
if (tweetQueue.Count > 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
HideNotification(true);
|
||||||
|
TrimQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResumeNotification(){
|
||||||
|
bool wasPaused = IsPaused;
|
||||||
|
base.ResumeNotification();
|
||||||
|
|
||||||
|
if (wasPaused && !IsPaused && !pausedDuringNotification && tweetQueue.Count > 0){
|
||||||
|
LoadNextNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadNextNotification(){
|
||||||
|
if (!IsNotificationVisible){
|
||||||
|
if (Program.UserConfig.NotificationNonIntrusiveMode && IsCursorOverNotificationArea && NativeMethods.GetIdleSeconds() < NonIntrusiveIdleLimit){
|
||||||
|
if (!timerCursorCheck.Enabled){
|
||||||
|
PauseNotification();
|
||||||
|
timerCursorCheck.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Program.UserConfig.NotificationIdlePauseSeconds > 0 && NativeMethods.GetIdleSeconds() >= Program.UserConfig.NotificationIdlePauseSeconds){
|
||||||
|
if (!timerIdlePauseCheck.Enabled){
|
||||||
|
PauseNotification();
|
||||||
|
timerIdlePauseCheck.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadTweet(tweetQueue.Dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateTitle(){
|
||||||
|
base.UpdateTitle();
|
||||||
|
|
||||||
|
if (tweetQueue.Count > 0){
|
||||||
|
Text = Text+" ("+tweetQueue.Count+" more left)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNotificationReady(){
|
||||||
|
UpdateTitle();
|
||||||
|
base.OnNotificationReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
|
using TweetDuck.Core.Bridge;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification.Screenshot{
|
||||||
|
sealed class FormNotificationScreenshotable : FormNotificationBase{
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
|
public FormNotificationScreenshotable(Action callback, Form owner, PluginManager pluginManager) : base(owner, false){
|
||||||
|
this.plugins = pluginManager;
|
||||||
|
|
||||||
|
browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new CallbackBridge(this, callback));
|
||||||
|
|
||||||
|
browser.LoadingStateChanged += (sender, args) => {
|
||||||
|
if (!args.IsLoading){
|
||||||
|
using(IFrame frame = args.Browser.MainFrame){
|
||||||
|
ScriptLoader.ExecuteScript(frame, "window.setTimeout($TD_NotificationScreenshot.trigger, 129)", "gen:screenshot");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetTweetHTML(TweetNotification tweet){
|
||||||
|
string html = tweet.GenerateHtml("td-screenshot", false);
|
||||||
|
|
||||||
|
foreach(InjectedHTML injection in plugins.Bridge.NotificationInjections){
|
||||||
|
html = injection.Inject(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadNotificationForScreenshot(TweetNotification tweet, int width, int height){
|
||||||
|
LoadTweet(tweet);
|
||||||
|
SetNotificationSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TakeScreenshot(){
|
||||||
|
IntPtr context = NativeMethods.GetDC(this.Handle);
|
||||||
|
|
||||||
|
if (context == IntPtr.Zero){
|
||||||
|
FormMessage.Error("Screenshot Failed", "Could not retrieve a graphics context handle for the notification window to take the screenshot.", FormMessage.OK);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
using(Bitmap bmp = new Bitmap(ClientSize.Width, ClientSize.Height, PixelFormat.Format32bppRgb)){
|
||||||
|
try{
|
||||||
|
NativeMethods.RenderSourceIntoBitmap(context, bmp);
|
||||||
|
}finally{
|
||||||
|
NativeMethods.ReleaseDC(this.Handle, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
Clipboard.SetImage(bmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
Core/Notification/Screenshot/TweetScreenshotManager.cs
Normal file
86
Core/Notification/Screenshot/TweetScreenshotManager.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Uncomment to keep screenshot windows visible for debugging
|
||||||
|
// #define NO_HIDE_SCREENSHOTS
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification.Screenshot{
|
||||||
|
sealed class TweetScreenshotManager : IDisposable{
|
||||||
|
private readonly FormBrowser owner;
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
private readonly Timer timeout;
|
||||||
|
private readonly Timer disposer;
|
||||||
|
|
||||||
|
private FormNotificationScreenshotable screenshot;
|
||||||
|
|
||||||
|
public TweetScreenshotManager(FormBrowser owner, PluginManager pluginManager){
|
||||||
|
this.owner = owner;
|
||||||
|
this.plugins = pluginManager;
|
||||||
|
|
||||||
|
this.timeout = new Timer{ Interval = 8000 };
|
||||||
|
this.timeout.Tick += timeout_Tick;
|
||||||
|
|
||||||
|
this.disposer = new Timer{ Interval = 1 };
|
||||||
|
this.disposer.Tick += disposer_Tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timeout_Tick(object sender, EventArgs e){
|
||||||
|
timeout.Stop();
|
||||||
|
OnFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disposer_Tick(object sender, EventArgs e){
|
||||||
|
disposer.Stop();
|
||||||
|
screenshot.Dispose();
|
||||||
|
screenshot = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trigger(string html, int width, int height){
|
||||||
|
if (screenshot != null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
screenshot = new FormNotificationScreenshotable(Callback, owner, plugins){
|
||||||
|
CanMoveWindow = () => false
|
||||||
|
};
|
||||||
|
|
||||||
|
screenshot.LoadNotificationForScreenshot(new TweetNotification(string.Empty, html, 0, string.Empty, string.Empty), width, height);
|
||||||
|
screenshot.Show();
|
||||||
|
timeout.Start();
|
||||||
|
|
||||||
|
#if !(DEBUG && NO_HIDE_SCREENSHOTS)
|
||||||
|
owner.IsWaiting = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Callback(){
|
||||||
|
if (!timeout.Enabled){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout.Stop();
|
||||||
|
screenshot.TakeScreenshot();
|
||||||
|
|
||||||
|
#if !(DEBUG && NO_HIDE_SCREENSHOTS)
|
||||||
|
OnFinished();
|
||||||
|
#else
|
||||||
|
screenshot.MoveToVisibleLocation();
|
||||||
|
screenshot.FormClosed += (sender, args) => disposer.Start();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFinished(){
|
||||||
|
screenshot.Location = ControlExtensions.InvisibleLocation;
|
||||||
|
owner.IsWaiting = false;
|
||||||
|
disposer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
timeout.Dispose();
|
||||||
|
disposer.Dispose();
|
||||||
|
screenshot?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Core/Notification/SoundNotification.cs
Normal file
28
Core/Notification/SoundNotification.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using TweetLib.Audio;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification{
|
||||||
|
sealed class SoundNotification : IDisposable{
|
||||||
|
public string SupportedFormats => player.SupportedFormats;
|
||||||
|
public event EventHandler<PlaybackErrorEventArgs> PlaybackError;
|
||||||
|
|
||||||
|
private readonly AudioPlayer player;
|
||||||
|
|
||||||
|
public SoundNotification(){
|
||||||
|
this.player = AudioPlayer.New();
|
||||||
|
this.player.PlaybackError += Player_PlaybackError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Play(string file){
|
||||||
|
player.Play(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Player_PlaybackError(object sender, PlaybackErrorEventArgs e){
|
||||||
|
PlaybackError?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
player.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
110
Core/Notification/TweetNotification.cs
Normal file
110
Core/Notification/TweetNotification.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using TweetDuck.Resources;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Notification{
|
||||||
|
sealed class TweetNotification{
|
||||||
|
private static string FontSizeClass { get; set; }
|
||||||
|
private static string HeadTag { get; set; }
|
||||||
|
|
||||||
|
private const string DefaultFontSizeClass = "medium";
|
||||||
|
private const string DefaultHeadTag = @"<meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='chrome=1'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/font.5ef884f9f9.css'><link rel='stylesheet' href='https://ton.twimg.com/tweetdeck-web/web/css/app-dark.5631e0dd42.css'><style type='text/css'>body{background:#222426}</style>";
|
||||||
|
private const string CustomCSS = @"body:before{content:none}body{overflow-y:auto}.scroll-styled-v::-webkit-scrollbar{width:7px}.scroll-styled-v::-webkit-scrollbar-thumb{border-radius:0}.scroll-styled-v::-webkit-scrollbar-track{border-left:0}#td-skip{opacity:0;cursor:pointer;transition:opacity 0.15s ease}.td-hover #td-skip{opacity:0.75}#td-skip:hover{opacity:1}.media-size-medium{height:calc(100vh - 16px)!important;max-height:240px;border-radius:1px!important}.js-quote-detail .media-size-medium{height:calc(100vh - 28px)!important;}.js-media.margin-vm, .js-media-preview-container.margin-vm{margin-bottom:0!important}";
|
||||||
|
|
||||||
|
public static int FontSizeLevel{
|
||||||
|
get{
|
||||||
|
switch(FontSizeClass){
|
||||||
|
case "largest": return 4;
|
||||||
|
case "large": return 3;
|
||||||
|
case "medium": return 2;
|
||||||
|
case "small": return 1;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExampleTweetHTML;
|
||||||
|
|
||||||
|
public static TweetNotification ExampleTweet{
|
||||||
|
get{
|
||||||
|
if (ExampleTweetHTML == null){
|
||||||
|
ExampleTweetHTML = ScriptLoader.LoadResource("pages/example.html", true);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
ExampleTweetHTML = ExampleTweetHTML.Replace("</p>", @"</p><div style='margin-top:256px'>Scrollbar test padding...</div>");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TweetNotification("Home", ExampleTweetHTML, 95, string.Empty, string.Empty, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetFontSizeClass(string newFSClass){
|
||||||
|
FontSizeClass = newFSClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetHeadTag(string headContents){
|
||||||
|
HeadTag = headContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Position{
|
||||||
|
TopLeft, TopRight, BottomLeft, BottomRight, Custom
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Size{
|
||||||
|
Auto, Custom
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Column { get; }
|
||||||
|
public string TweetUrl { get; }
|
||||||
|
public string QuoteUrl { get; }
|
||||||
|
|
||||||
|
private readonly string html;
|
||||||
|
private readonly int characters;
|
||||||
|
private readonly bool isExample;
|
||||||
|
|
||||||
|
public TweetNotification(string column, string html, int characters, string tweetUrl, string quoteUrl) : this(column, html, characters, tweetUrl, quoteUrl, false){}
|
||||||
|
|
||||||
|
private TweetNotification(string column, string html, int characters, string tweetUrl, string quoteUrl, bool isExample){
|
||||||
|
this.Column = column;
|
||||||
|
this.TweetUrl = tweetUrl;
|
||||||
|
this.QuoteUrl = quoteUrl;
|
||||||
|
|
||||||
|
this.html = html;
|
||||||
|
this.characters = characters;
|
||||||
|
this.isExample = isExample;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetDisplayDuration(int value){
|
||||||
|
return 2000+Math.Max(1000, value*characters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateHtml(string bodyClasses = null, bool enableCustomCSS = true){
|
||||||
|
StringBuilder build = new StringBuilder();
|
||||||
|
build.Append("<!DOCTYPE html>");
|
||||||
|
build.Append("<html class='os-windows txt-base-").Append(FontSizeClass ?? DefaultFontSizeClass).Append("'>");
|
||||||
|
build.Append("<head>").Append(HeadTag ?? DefaultHeadTag);
|
||||||
|
|
||||||
|
if (enableCustomCSS){
|
||||||
|
build.Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
|
||||||
|
build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.Append("</head>");
|
||||||
|
build.Append("<body class='scroll-styled-v");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(bodyClasses)){
|
||||||
|
build.Append(' ').Append(bodyClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
build.Append('\'').Append(isExample ? " td-example-notification" : "").Append("><div class='column' style='width:100%;height:auto;overflow:initial;'>");
|
||||||
|
build.Append(html);
|
||||||
|
build.Append("</div></body>");
|
||||||
|
build.Append("</html>");
|
||||||
|
return build.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Core/Other/FormAbout.Designer.cs
generated
17
Core/Other/FormAbout.Designer.cs
generated
@@ -1,6 +1,4 @@
|
|||||||
using TweetDck.Core.Controls;
|
namespace TweetDuck.Core.Other {
|
||||||
|
|
||||||
namespace TweetDck.Core.Other {
|
|
||||||
sealed partial class FormAbout {
|
sealed partial class FormAbout {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -57,7 +55,7 @@ namespace TweetDck.Core.Other {
|
|||||||
this.labelDescription.Location = new System.Drawing.Point(114, 12);
|
this.labelDescription.Location = new System.Drawing.Point(114, 12);
|
||||||
this.labelDescription.Name = "labelDescription";
|
this.labelDescription.Name = "labelDescription";
|
||||||
this.labelDescription.Size = new System.Drawing.Size(232, 109);
|
this.labelDescription.Size = new System.Drawing.Size(232, 109);
|
||||||
this.labelDescription.TabIndex = 1;
|
this.labelDescription.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// labelTips
|
// labelTips
|
||||||
//
|
//
|
||||||
@@ -68,7 +66,8 @@ namespace TweetDck.Core.Other {
|
|||||||
this.labelTips.Margin = new System.Windows.Forms.Padding(0);
|
this.labelTips.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.labelTips.Name = "labelTips";
|
this.labelTips.Name = "labelTips";
|
||||||
this.labelTips.Size = new System.Drawing.Size(99, 16);
|
this.labelTips.Size = new System.Drawing.Size(99, 16);
|
||||||
this.labelTips.TabIndex = 3;
|
this.labelTips.TabIndex = 1;
|
||||||
|
this.labelTips.TabStop = true;
|
||||||
this.labelTips.Text = "Tips && Tricks";
|
this.labelTips.Text = "Tips && Tricks";
|
||||||
this.labelTips.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
this.labelTips.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
this.labelTips.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
this.labelTips.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
@@ -83,7 +82,8 @@ namespace TweetDck.Core.Other {
|
|||||||
this.labelWebsite.Margin = new System.Windows.Forms.Padding(0);
|
this.labelWebsite.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.labelWebsite.Name = "labelWebsite";
|
this.labelWebsite.Name = "labelWebsite";
|
||||||
this.labelWebsite.Size = new System.Drawing.Size(117, 16);
|
this.labelWebsite.Size = new System.Drawing.Size(117, 16);
|
||||||
this.labelWebsite.TabIndex = 2;
|
this.labelWebsite.TabIndex = 0;
|
||||||
|
this.labelWebsite.TabStop = true;
|
||||||
this.labelWebsite.Text = "Official Website";
|
this.labelWebsite.Text = "Official Website";
|
||||||
this.labelWebsite.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
this.labelWebsite.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
this.labelWebsite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
this.labelWebsite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
@@ -104,7 +104,7 @@ namespace TweetDck.Core.Other {
|
|||||||
this.tablePanelLinks.RowCount = 1;
|
this.tablePanelLinks.RowCount = 1;
|
||||||
this.tablePanelLinks.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
this.tablePanelLinks.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
this.tablePanelLinks.Size = new System.Drawing.Size(334, 16);
|
this.tablePanelLinks.Size = new System.Drawing.Size(334, 16);
|
||||||
this.tablePanelLinks.TabIndex = 4;
|
this.tablePanelLinks.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// labelIssues
|
// labelIssues
|
||||||
//
|
//
|
||||||
@@ -115,7 +115,8 @@ namespace TweetDck.Core.Other {
|
|||||||
this.labelIssues.Margin = new System.Windows.Forms.Padding(0);
|
this.labelIssues.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.labelIssues.Name = "labelIssues";
|
this.labelIssues.Name = "labelIssues";
|
||||||
this.labelIssues.Size = new System.Drawing.Size(118, 16);
|
this.labelIssues.Size = new System.Drawing.Size(118, 16);
|
||||||
this.labelIssues.TabIndex = 4;
|
this.labelIssues.TabIndex = 2;
|
||||||
|
this.labelIssues.TabStop = true;
|
||||||
this.labelIssues.Text = "Report an Issue";
|
this.labelIssues.Text = "Report an Issue";
|
||||||
this.labelIssues.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
this.labelIssues.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
this.labelIssues.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
this.labelIssues.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormAbout : Form{
|
sealed partial class FormAbout : Form{
|
||||||
private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
|
private const string TipsLink = "https://github.com/chylex/TweetDuck/wiki";
|
||||||
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
|
private const string IssuesLink = "https://github.com/chylex/TweetDuck/issues";
|
||||||
@@ -11,7 +11,7 @@ namespace TweetDck.Core.Other{
|
|||||||
|
|
||||||
Text = "About "+Program.BrandName+" "+Program.VersionTag;
|
Text = "About "+Program.BrandName+" "+Program.VersionTag;
|
||||||
|
|
||||||
labelDescription.Text = Program.BrandName+" was created by chylex as a replacement to the discontinued official TweetDeck client for Windows.\n\nThe program is available for free under the open source MIT license.";
|
labelDescription.Text = "TweetDuck was created by chylex as a replacement to the discontinued official TweetDeck client for Windows.\n\nThe program is available for free under the open source MIT license.";
|
||||||
|
|
||||||
labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website));
|
labelWebsite.Links.Add(new LinkLabel.Link(0, labelWebsite.Text.Length, Program.Website));
|
||||||
labelTips.Links.Add(new LinkLabel.Link(0, labelTips.Text.Length, TipsLink));
|
labelTips.Links.Add(new LinkLabel.Link(0, labelTips.Text.Length, TipsLink));
|
||||||
@@ -19,7 +19,7 @@ namespace TweetDck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void OnLinkClicked(object sender, LinkLabelLinkClickedEventArgs e){
|
private void OnLinkClicked(object sender, LinkLabelLinkClickedEventArgs e){
|
||||||
BrowserUtils.OpenExternalBrowser(e.Link.LinkData as string);
|
BrowserUtils.OpenExternalBrowserUnsafe(e.Link.LinkData as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Core/Other/FormMessage.Designer.cs
generated
9
Core/Other/FormMessage.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other {
|
namespace TweetDuck.Core.Other {
|
||||||
partial class FormMessage {
|
partial class FormMessage {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
this.panelActions.Dock = System.Windows.Forms.DockStyle.Bottom;
|
this.panelActions.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
this.panelActions.Location = new System.Drawing.Point(0, 84);
|
this.panelActions.Location = new System.Drawing.Point(0, 84);
|
||||||
this.panelActions.Name = "panelActions";
|
this.panelActions.Name = "panelActions";
|
||||||
this.panelActions.Size = new System.Drawing.Size(233, 49);
|
this.panelActions.Size = new System.Drawing.Size(98, 49);
|
||||||
this.panelActions.TabIndex = 0;
|
this.panelActions.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// labelMessage
|
// labelMessage
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.labelMessage.AutoSize = true;
|
this.labelMessage.AutoSize = true;
|
||||||
this.labelMessage.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.labelMessage.Font = System.Drawing.SystemFonts.MessageBoxFont;
|
||||||
this.labelMessage.Location = new System.Drawing.Point(62, 33);
|
this.labelMessage.Location = new System.Drawing.Point(62, 34);
|
||||||
this.labelMessage.Margin = new System.Windows.Forms.Padding(53, 24, 27, 24);
|
this.labelMessage.Margin = new System.Windows.Forms.Padding(53, 24, 27, 24);
|
||||||
this.labelMessage.MaximumSize = new System.Drawing.Size(600, 0);
|
this.labelMessage.MaximumSize = new System.Drawing.Size(600, 0);
|
||||||
this.labelMessage.MinimumSize = new System.Drawing.Size(0, 24);
|
this.labelMessage.MinimumSize = new System.Drawing.Size(0, 24);
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
this.Name = "FormMessage";
|
this.Name = "FormMessage";
|
||||||
this.ShowIcon = false;
|
this.ShowIcon = false;
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
|
this.SizeChanged += new System.EventHandler(this.FormMessage_SizeChanged);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,79 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other{
|
||||||
|
[Flags]
|
||||||
|
enum ControlType{
|
||||||
|
None = 0,
|
||||||
|
Accept = 1, // triggered by pressing enter when a non-button is focused
|
||||||
|
Cancel = 2, // triggered by closing the dialog without pressing a button
|
||||||
|
Focused = 4 // active control after the dialog is showed
|
||||||
|
}
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
|
||||||
sealed partial class FormMessage : Form{
|
sealed partial class FormMessage : Form{
|
||||||
|
public const string OK = "OK";
|
||||||
|
public const string Yes = "Yes";
|
||||||
|
public const string No = "No";
|
||||||
|
public const string Cancel = "Cancel";
|
||||||
|
public const string Retry = "Retry";
|
||||||
|
public const string Ignore = "Ignore";
|
||||||
|
public const string Exit = "Exit";
|
||||||
|
|
||||||
|
public static bool Information(string caption, string text, string buttonAccept, string buttonCancel = null){
|
||||||
|
return Show(caption, text, MessageBoxIcon.Information, buttonAccept, buttonCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Warning(string caption, string text, string buttonAccept, string buttonCancel = null){
|
||||||
|
return Show(caption, text, MessageBoxIcon.Warning, buttonAccept, buttonCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Error(string caption, string text, string buttonAccept, string buttonCancel = null){
|
||||||
|
return Show(caption, text, MessageBoxIcon.Error, buttonAccept, buttonCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Question(string caption, string text, string buttonAccept, string buttonCancel = null){
|
||||||
|
return Show(caption, text, MessageBoxIcon.Question, buttonAccept, buttonCancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Show(string caption, string text, MessageBoxIcon icon, string button){
|
||||||
|
return Show(caption, text, icon, button, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Show(string caption, string text, MessageBoxIcon icon, string buttonAccept, string buttonCancel){
|
||||||
|
using(FormMessage message = new FormMessage(caption, text, icon)){
|
||||||
|
if (buttonCancel == null){
|
||||||
|
message.AddButton(buttonAccept, DialogResult.OK, ControlType.Cancel | ControlType.Focused);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
message.AddButton(buttonCancel, DialogResult.Cancel, ControlType.Cancel);
|
||||||
|
message.AddButton(buttonAccept, DialogResult.OK, ControlType.Accept | ControlType.Focused);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message.ShowDialog() == DialogResult.OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance
|
||||||
|
|
||||||
public Button ClickedButton { get; private set; }
|
public Button ClickedButton { get; private set; }
|
||||||
|
|
||||||
|
public int ActionPanelY => panelActions.Location.Y;
|
||||||
|
|
||||||
|
private int ClientWidth{
|
||||||
|
get => ClientSize.Width;
|
||||||
|
set => ClientSize = new Size(value, ClientSize.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ButtonDistance{
|
||||||
|
get => BrowserUtils.Scale(96, dpiScale);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly Icon icon;
|
private readonly Icon icon;
|
||||||
private readonly bool isReady;
|
private readonly bool isReady;
|
||||||
|
private readonly float dpiScale;
|
||||||
|
|
||||||
private int realFormWidth, minFormWidth;
|
private int realFormWidth, minFormWidth;
|
||||||
private int buttonCount;
|
private int buttonCount;
|
||||||
@@ -17,9 +83,11 @@ namespace TweetDck.Core.Other{
|
|||||||
public FormMessage(string caption, string text, MessageBoxIcon messageIcon){
|
public FormMessage(string caption, string text, MessageBoxIcon messageIcon){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.dpiScale = this.GetDPIScale();
|
||||||
|
|
||||||
this.prevLabelWidth = labelMessage.Width;
|
this.prevLabelWidth = labelMessage.Width;
|
||||||
this.prevLabelHeight = labelMessage.Height;
|
this.prevLabelHeight = labelMessage.Height;
|
||||||
this.minFormWidth = 18;
|
this.minFormWidth = BrowserUtils.Scale(42, dpiScale);
|
||||||
|
|
||||||
switch(messageIcon){
|
switch(messageIcon){
|
||||||
case MessageBoxIcon.Information:
|
case MessageBoxIcon.Information:
|
||||||
@@ -40,21 +108,30 @@ namespace TweetDck.Core.Other{
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
icon = null;
|
icon = null;
|
||||||
labelMessage.Location = new Point(labelMessage.Location.X-32, labelMessage.Location.Y);
|
labelMessage.Location = new Point(BrowserUtils.Scale(19, dpiScale), labelMessage.Location.Y); // 19 instead of 9 due to larger height
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isReady = true;
|
this.isReady = true;
|
||||||
|
|
||||||
this.Text = caption;
|
this.Text = caption;
|
||||||
this.labelMessage.Text = text;
|
this.labelMessage.Text = text.Replace("\r", "").Replace("\n", Environment.NewLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Button AddButton(string title){
|
private void FormMessage_SizeChanged(object sender, EventArgs e){
|
||||||
|
RecalculateButtonLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button AddButton(string title, ControlType type){
|
||||||
|
return AddButton(title, DialogResult.OK, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button AddButton(string title, DialogResult result = DialogResult.OK, ControlType type = ControlType.None){
|
||||||
Button button = new Button{
|
Button button = new Button{
|
||||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
Anchor = AnchorStyles.Bottom,
|
||||||
Location = new Point(Width-112-buttonCount*96, 12),
|
Font = SystemFonts.MessageBoxFont,
|
||||||
Size = new Size(88, 26),
|
Location = new Point(0, 12),
|
||||||
|
Size = new Size(BrowserUtils.Scale(88, dpiScale), BrowserUtils.Scale(26, dpiScale)),
|
||||||
TabIndex = buttonCount,
|
TabIndex = buttonCount,
|
||||||
Text = title,
|
Text = title,
|
||||||
UseVisualStyleBackColor = true
|
UseVisualStyleBackColor = true
|
||||||
@@ -62,24 +139,49 @@ namespace TweetDck.Core.Other{
|
|||||||
|
|
||||||
button.Click += (sender, args) => {
|
button.Click += (sender, args) => {
|
||||||
ClickedButton = (Button)sender;
|
ClickedButton = (Button)sender;
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = result;
|
||||||
Close();
|
Close();
|
||||||
};
|
};
|
||||||
|
|
||||||
panelActions.Controls.Add(button);
|
panelActions.Controls.Add(button);
|
||||||
|
|
||||||
minFormWidth += 96;
|
|
||||||
Width = Math.Max(realFormWidth, minFormWidth);
|
|
||||||
|
|
||||||
++buttonCount;
|
++buttonCount;
|
||||||
|
|
||||||
|
minFormWidth += ButtonDistance;
|
||||||
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
|
RecalculateButtonLocation();
|
||||||
|
|
||||||
|
if (type.HasFlag(ControlType.Accept)){
|
||||||
|
AcceptButton = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.HasFlag(ControlType.Cancel)){
|
||||||
|
CancelButton = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.HasFlag(ControlType.Focused)){
|
||||||
|
ActiveControl = button;
|
||||||
|
}
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddActionControl(Control control){
|
public void AddActionControl(Control control){
|
||||||
panelActions.Controls.Add(control);
|
panelActions.Controls.Add(control);
|
||||||
|
|
||||||
|
control.Size = new Size(BrowserUtils.Scale(control.Width, dpiScale), BrowserUtils.Scale(control.Height, dpiScale));
|
||||||
|
|
||||||
minFormWidth += control.Width+control.Margin.Horizontal;
|
minFormWidth += control.Width+control.Margin.Horizontal;
|
||||||
Width = Math.Max(realFormWidth, minFormWidth);
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecalculateButtonLocation(){
|
||||||
|
int dist = ButtonDistance;
|
||||||
|
int start = ClientWidth-dist;
|
||||||
|
|
||||||
|
for(int index = 0; index < buttonCount; index++){
|
||||||
|
Control control = panelActions.Controls[index];
|
||||||
|
control.Location = new Point(start-index*dist, control.Location.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void labelMessage_SizeChanged(object sender, EventArgs e){
|
private void labelMessage_SizeChanged(object sender, EventArgs e){
|
||||||
@@ -88,18 +190,19 @@ namespace TweetDck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isMultiline = labelMessage.Height > labelMessage.MinimumSize.Height;
|
bool isMultiline = labelMessage.Height > labelMessage.MinimumSize.Height;
|
||||||
|
int labelOffset = BrowserUtils.Scale(8, dpiScale);
|
||||||
|
|
||||||
if (isMultiline && !wasLabelMultiline){
|
if (isMultiline && !wasLabelMultiline){
|
||||||
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y-8);
|
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y-labelOffset);
|
||||||
prevLabelHeight += 8;
|
prevLabelHeight += labelOffset;
|
||||||
}
|
}
|
||||||
else if (!isMultiline && wasLabelMultiline){
|
else if (!isMultiline && wasLabelMultiline){
|
||||||
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y+8);
|
labelMessage.Location = new Point(labelMessage.Location.X, labelMessage.Location.Y+labelOffset);
|
||||||
prevLabelHeight -= 8;
|
prevLabelHeight -= labelOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
realFormWidth = Width-(icon == null ? 32+35+(labelMessage.Margin.Left-labelMessage.Margin.Right) : 0)+labelMessage.Margin.Right+labelMessage.Width-prevLabelWidth;
|
realFormWidth = ClientWidth-(icon == null ? BrowserUtils.Scale(50, dpiScale) : 0)+labelMessage.Width-prevLabelWidth;
|
||||||
Width = Math.Max(realFormWidth, minFormWidth);
|
ClientWidth = Math.Max(realFormWidth, minFormWidth);
|
||||||
Height += labelMessage.Height-prevLabelHeight;
|
Height += labelMessage.Height-prevLabelHeight;
|
||||||
|
|
||||||
prevLabelWidth = labelMessage.Width;
|
prevLabelWidth = labelMessage.Width;
|
||||||
@@ -109,7 +212,7 @@ namespace TweetDck.Core.Other{
|
|||||||
|
|
||||||
protected override void OnPaint(PaintEventArgs e){
|
protected override void OnPaint(PaintEventArgs e){
|
||||||
if (icon != null){
|
if (icon != null){
|
||||||
e.Graphics.DrawIcon(icon, 25, 26);
|
e.Graphics.DrawIcon(icon, BrowserUtils.Scale(25, dpiScale), 1+BrowserUtils.Scale(25, dpiScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnPaint(e);
|
base.OnPaint(e);
|
||||||
|
|||||||
26
Core/Other/FormPlugins.Designer.cs
generated
26
Core/Other/FormPlugins.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other {
|
namespace TweetDuck.Core.Other {
|
||||||
partial class FormPlugins {
|
partial class FormPlugins {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
this.btnClose = new System.Windows.Forms.Button();
|
this.btnClose = new System.Windows.Forms.Button();
|
||||||
this.btnReload = new System.Windows.Forms.Button();
|
this.btnReload = new System.Windows.Forms.Button();
|
||||||
this.btnOpenFolder = new System.Windows.Forms.Button();
|
this.btnOpenFolder = new System.Windows.Forms.Button();
|
||||||
this.tabPanelPlugins = new TweetDck.Core.Controls.TabPanel();
|
this.flowLayoutPlugins = new TweetDuck.Plugins.Controls.PluginListFlowLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// btnClose
|
// btnClose
|
||||||
@@ -68,26 +68,30 @@
|
|||||||
this.btnOpenFolder.UseVisualStyleBackColor = true;
|
this.btnOpenFolder.UseVisualStyleBackColor = true;
|
||||||
this.btnOpenFolder.Click += new System.EventHandler(this.btnOpenFolder_Click);
|
this.btnOpenFolder.Click += new System.EventHandler(this.btnOpenFolder_Click);
|
||||||
//
|
//
|
||||||
// tabPanelPlugins
|
// flowLayoutPlugins
|
||||||
//
|
//
|
||||||
this.tabPanelPlugins.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.flowLayoutPlugins.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.tabPanelPlugins.Location = new System.Drawing.Point(12, 12);
|
this.flowLayoutPlugins.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
this.tabPanelPlugins.Name = "tabPanelPlugins";
|
this.flowLayoutPlugins.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
|
||||||
this.tabPanelPlugins.Size = new System.Drawing.Size(680, 421);
|
this.flowLayoutPlugins.Location = new System.Drawing.Point(12, 12);
|
||||||
this.tabPanelPlugins.TabIndex = 4;
|
this.flowLayoutPlugins.Name = "flowLayoutPlugins";
|
||||||
|
this.flowLayoutPlugins.Size = new System.Drawing.Size(680, 421);
|
||||||
|
this.flowLayoutPlugins.TabIndex = 0;
|
||||||
|
this.flowLayoutPlugins.WrapContents = false;
|
||||||
|
this.flowLayoutPlugins.Resize += new System.EventHandler(this.flowLayoutPlugins_Resize);
|
||||||
//
|
//
|
||||||
// FormPlugins
|
// FormPlugins
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(704, 474);
|
this.ClientSize = new System.Drawing.Size(704, 474);
|
||||||
this.Controls.Add(this.tabPanelPlugins);
|
this.Controls.Add(this.flowLayoutPlugins);
|
||||||
this.Controls.Add(this.btnOpenFolder);
|
this.Controls.Add(this.btnOpenFolder);
|
||||||
this.Controls.Add(this.btnReload);
|
this.Controls.Add(this.btnReload);
|
||||||
this.Controls.Add(this.btnClose);
|
this.Controls.Add(this.btnClose);
|
||||||
this.Icon = global::TweetDck.Properties.Resources.icon;
|
this.Icon = global::TweetDuck.Properties.Resources.icon;
|
||||||
this.MinimumSize = new System.Drawing.Size(480, 320);
|
this.MinimumSize = new System.Drawing.Size(480, 320);
|
||||||
this.Name = "FormPlugins";
|
this.Name = "FormPlugins";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
@@ -101,6 +105,6 @@
|
|||||||
private System.Windows.Forms.Button btnClose;
|
private System.Windows.Forms.Button btnClose;
|
||||||
private System.Windows.Forms.Button btnReload;
|
private System.Windows.Forms.Button btnReload;
|
||||||
private System.Windows.Forms.Button btnOpenFolder;
|
private System.Windows.Forms.Button btnOpenFolder;
|
||||||
private TweetDck.Core.Controls.TabPanel tabPanelPlugins;
|
private Plugins.Controls.PluginListFlowLayout flowLayoutPlugins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,18 +3,12 @@ using System.Diagnostics;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Plugins;
|
||||||
using TweetDck.Plugins;
|
using TweetDuck.Plugins.Controls;
|
||||||
using TweetDck.Plugins.Controls;
|
|
||||||
using TweetDck.Plugins.Events;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormPlugins : Form{
|
sealed partial class FormPlugins : Form{
|
||||||
private readonly PluginManager pluginManager;
|
private readonly PluginManager pluginManager;
|
||||||
private readonly TabButton tabBtnOfficial, tabBtnCustom;
|
|
||||||
private readonly PluginListFlowLayout flowLayoutPlugins;
|
|
||||||
|
|
||||||
private PluginGroup? selectedGroup;
|
|
||||||
|
|
||||||
public FormPlugins(){
|
public FormPlugins(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -24,22 +18,10 @@ namespace TweetDck.Core.Other{
|
|||||||
|
|
||||||
public FormPlugins(PluginManager pluginManager) : this(){
|
public FormPlugins(PluginManager pluginManager) : this(){
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
this.pluginManager.Reloaded += pluginManager_Reloaded;
|
|
||||||
|
|
||||||
this.flowLayoutPlugins = new PluginListFlowLayout();
|
|
||||||
this.flowLayoutPlugins.Resize += flowLayoutPlugins_Resize;
|
|
||||||
|
|
||||||
this.tabPanelPlugins.SetupTabPanel(90);
|
|
||||||
this.tabPanelPlugins.ReplaceContent(flowLayoutPlugins);
|
|
||||||
|
|
||||||
this.tabBtnOfficial = tabPanelPlugins.AddButton("", () => SelectGroup(PluginGroup.Official));
|
|
||||||
this.tabBtnCustom = tabPanelPlugins.AddButton("", () => SelectGroup(PluginGroup.Custom));
|
|
||||||
|
|
||||||
this.tabPanelPlugins.SelectTab(tabBtnOfficial);
|
|
||||||
this.pluginManager_Reloaded(pluginManager, null);
|
|
||||||
|
|
||||||
Shown += (sender, args) => {
|
Shown += (sender, args) => {
|
||||||
Program.UserConfig.PluginsWindow.Restore(this, false);
|
Program.UserConfig.PluginsWindow.Restore(this, false);
|
||||||
|
ReloadPluginList();
|
||||||
};
|
};
|
||||||
|
|
||||||
FormClosed += (sender, args) => {
|
FormClosed += (sender, args) => {
|
||||||
@@ -48,40 +30,29 @@ namespace TweetDck.Core.Other{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectGroup(PluginGroup group){
|
private int GetPluginOrderIndex(Plugin plugin){
|
||||||
if (selectedGroup.HasValue && selectedGroup == group)return;
|
return !plugin.CanRun ? 0 : pluginManager.Config.IsEnabled(plugin) ? 1 : 2;
|
||||||
|
|
||||||
selectedGroup = group;
|
|
||||||
|
|
||||||
ReloadPluginTab();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadPluginTab(){
|
private void ReloadPluginList(){
|
||||||
if (!selectedGroup.HasValue)return;
|
|
||||||
|
|
||||||
flowLayoutPlugins.SuspendLayout();
|
flowLayoutPlugins.SuspendLayout();
|
||||||
flowLayoutPlugins.Controls.Clear();
|
flowLayoutPlugins.Controls.Clear();
|
||||||
|
|
||||||
Plugin[] plugins = pluginManager.GetPluginsByGroup(selectedGroup.Value).OrderBy(plugin => !plugin.CanRun ? 0 : pluginManager.Config.IsEnabled(plugin) ? 1 : 2).ThenBy(plugin => plugin.Name).ToArray();
|
foreach(Plugin plugin in pluginManager.Plugins.OrderBy(GetPluginOrderIndex).ThenBy(plugin => plugin.Name)){
|
||||||
|
flowLayoutPlugins.Controls.Add(new PluginControl(pluginManager, plugin));
|
||||||
|
|
||||||
for(int index = 0; index < plugins.Length; index++){
|
|
||||||
flowLayoutPlugins.Controls.Add(new PluginControl(pluginManager, plugins[index]));
|
|
||||||
|
|
||||||
if (index < plugins.Length-1){
|
|
||||||
flowLayoutPlugins.Controls.Add(new Panel{
|
flowLayoutPlugins.Controls.Add(new Panel{
|
||||||
BackColor = Color.DimGray,
|
BackColor = Color.DimGray,
|
||||||
|
Margin = new Padding(0),
|
||||||
Size = new Size(1, 1)
|
Size = new Size(1, 1)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
flowLayoutPlugins_Resize(flowLayoutPlugins, new EventArgs());
|
|
||||||
flowLayoutPlugins.ResumeLayout(true);
|
flowLayoutPlugins.ResumeLayout(true);
|
||||||
}
|
|
||||||
|
|
||||||
private void pluginManager_Reloaded(object sender, PluginLoadEventArgs e){
|
// sorry, I guess...
|
||||||
tabBtnOfficial.Text = "Official: "+pluginManager.CountPluginByGroup(PluginGroup.Official);
|
Padding = new Padding(Padding.Left, Padding.Top, Padding.Right+1, Padding.Bottom);
|
||||||
tabBtnCustom.Text = "Custom: "+pluginManager.CountPluginByGroup(PluginGroup.Custom);
|
Padding = new Padding(Padding.Left, Padding.Top, Padding.Right-1, Padding.Bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void flowLayoutPlugins_Resize(object sender, EventArgs e){
|
private void flowLayoutPlugins_Resize(object sender, EventArgs e){
|
||||||
@@ -100,6 +71,7 @@ namespace TweetDck.Core.Other{
|
|||||||
control.Width = flowLayoutPlugins.Width-control.Margin.Horizontal-horizontalOffset;
|
control.Width = flowLayoutPlugins.Width-control.Margin.Horizontal-horizontalOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastControl.Visible = !showScrollBar;
|
||||||
flowLayoutPlugins.Focus();
|
flowLayoutPlugins.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,9 +80,9 @@ namespace TweetDck.Core.Other{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void btnReload_Click(object sender, EventArgs e){
|
private void btnReload_Click(object sender, EventArgs e){
|
||||||
if (MessageBox.Show("This will also reload the browser window. Do you want to proceed?", "Reloading Plugins", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
if (FormMessage.Warning("Reloading Plugins", "This will also reload the browser window. Do you want to proceed?", FormMessage.Yes, FormMessage.No)){
|
||||||
pluginManager.Reload();
|
pluginManager.Reload();
|
||||||
ReloadPluginTab();
|
ReloadPluginList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
||||||
74
Core/Other/FormSettings.Designer.cs
generated
74
Core/Other/FormSettings.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other {
|
namespace TweetDuck.Core.Other {
|
||||||
sealed partial class FormSettings {
|
sealed partial class FormSettings {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -24,52 +24,72 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.btnClose = new System.Windows.Forms.Button();
|
this.btnClose = new System.Windows.Forms.Button();
|
||||||
this.labelTip = new System.Windows.Forms.Label();
|
this.panelContents = new System.Windows.Forms.Panel();
|
||||||
this.tabPanel = new TweetDck.Core.Controls.TabPanel();
|
this.panelButtons = new System.Windows.Forms.Panel();
|
||||||
|
this.btnManageOptions = new System.Windows.Forms.Button();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// btnClose
|
// btnClose
|
||||||
//
|
//
|
||||||
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.btnClose.AutoSize = true;
|
this.btnClose.AutoSize = true;
|
||||||
this.btnClose.Location = new System.Drawing.Point(443, 331);
|
this.btnClose.Location = new System.Drawing.Point(449, 447);
|
||||||
this.btnClose.Name = "btnClose";
|
this.btnClose.Name = "btnClose";
|
||||||
this.btnClose.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
this.btnClose.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
this.btnClose.Size = new System.Drawing.Size(49, 23);
|
this.btnClose.Size = new System.Drawing.Size(49, 23);
|
||||||
this.btnClose.TabIndex = 4;
|
this.btnClose.TabIndex = 3;
|
||||||
this.btnClose.Text = "Close";
|
this.btnClose.Text = "Close";
|
||||||
this.btnClose.UseVisualStyleBackColor = true;
|
this.btnClose.UseVisualStyleBackColor = true;
|
||||||
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||||
//
|
//
|
||||||
// labelTip
|
// panelContents
|
||||||
//
|
//
|
||||||
this.labelTip.AutoSize = true;
|
this.panelContents.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
this.labelTip.Location = new System.Drawing.Point(12, 333);
|
|
||||||
this.labelTip.Name = "labelTip";
|
|
||||||
this.labelTip.Size = new System.Drawing.Size(310, 13);
|
|
||||||
this.labelTip.TabIndex = 5;
|
|
||||||
this.labelTip.Text = "Tip: Move your cursor over an option to see detailed explanation";
|
|
||||||
//
|
|
||||||
// tabPanel
|
|
||||||
//
|
|
||||||
this.tabPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.tabPanel.Location = new System.Drawing.Point(12, 12);
|
this.panelContents.AutoScroll = true;
|
||||||
this.tabPanel.Name = "tabPanel";
|
this.panelContents.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
this.tabPanel.Size = new System.Drawing.Size(480, 313);
|
this.panelContents.Location = new System.Drawing.Point(135, 12);
|
||||||
this.tabPanel.TabIndex = 3;
|
this.panelContents.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
|
||||||
|
this.panelContents.Name = "panelContents";
|
||||||
|
this.panelContents.Size = new System.Drawing.Size(363, 429);
|
||||||
|
this.panelContents.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// panelButtons
|
||||||
|
//
|
||||||
|
this.panelButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.panelButtons.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
|
this.panelButtons.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.panelButtons.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
|
||||||
|
this.panelButtons.Name = "panelButtons";
|
||||||
|
this.panelButtons.Size = new System.Drawing.Size(124, 429);
|
||||||
|
this.panelButtons.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// btnManageOptions
|
||||||
|
//
|
||||||
|
this.btnManageOptions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnManageOptions.AutoSize = true;
|
||||||
|
this.btnManageOptions.Location = new System.Drawing.Point(12, 447);
|
||||||
|
this.btnManageOptions.Name = "btnManageOptions";
|
||||||
|
this.btnManageOptions.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnManageOptions.Size = new System.Drawing.Size(101, 23);
|
||||||
|
this.btnManageOptions.TabIndex = 4;
|
||||||
|
this.btnManageOptions.Text = "Manage Options";
|
||||||
|
this.btnManageOptions.UseVisualStyleBackColor = true;
|
||||||
|
this.btnManageOptions.Click += new System.EventHandler(this.btnManageOptions_Click);
|
||||||
//
|
//
|
||||||
// FormSettings
|
// FormSettings
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(504, 366);
|
this.ClientSize = new System.Drawing.Size(510, 482);
|
||||||
this.Controls.Add(this.labelTip);
|
this.Controls.Add(this.btnManageOptions);
|
||||||
|
this.Controls.Add(this.panelContents);
|
||||||
|
this.Controls.Add(this.panelButtons);
|
||||||
this.Controls.Add(this.btnClose);
|
this.Controls.Add(this.btnClose);
|
||||||
this.Controls.Add(this.tabPanel);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
this.Icon = Properties.Resources.icon;
|
this.Icon = global::TweetDuck.Properties.Resources.icon;
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "FormSettings";
|
this.Name = "FormSettings";
|
||||||
@@ -81,9 +101,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private Controls.TabPanel tabPanel;
|
|
||||||
private System.Windows.Forms.Button btnClose;
|
private System.Windows.Forms.Button btnClose;
|
||||||
private System.Windows.Forms.Label labelTip;
|
private System.Windows.Forms.Panel panelContents;
|
||||||
|
private System.Windows.Forms.Panel panelButtons;
|
||||||
|
private System.Windows.Forms.Button btnManageOptions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,65 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Other.Settings;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Plugins;
|
using TweetDuck.Core.Other.Settings;
|
||||||
using TweetDck.Updates;
|
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using TweetDuck.Updates;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other{
|
namespace TweetDuck.Core.Other{
|
||||||
sealed partial class FormSettings : Form{
|
sealed partial class FormSettings : Form{
|
||||||
private readonly Dictionary<Type, BaseTabSettings> tabs = new Dictionary<Type, BaseTabSettings>(4);
|
private readonly FormBrowser browser;
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
|
||||||
public FormSettings(FormBrowser browserForm, PluginManager plugins, UpdateHandler updates){
|
private readonly int buttonHeight;
|
||||||
|
|
||||||
|
private readonly Dictionary<Type, SettingsTab> tabs = new Dictionary<Type, SettingsTab>(4);
|
||||||
|
private SettingsTab currentTab;
|
||||||
|
|
||||||
|
public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler updates, Type startTab){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName+" Settings";
|
Text = Program.BrandName+" Options";
|
||||||
|
|
||||||
this.tabPanel.SetupTabPanel(100);
|
this.browser = browser;
|
||||||
this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>);
|
this.browser.PauseNotification();
|
||||||
this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(false))));
|
|
||||||
this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates)));
|
|
||||||
this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browserForm.ReloadBrowser, plugins)));
|
|
||||||
this.tabPanel.SelectTab(tabPanel.Buttons.First());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SelectTab<T>() where T : BaseTabSettings, new(){
|
this.plugins = plugins;
|
||||||
SelectTab(() => new T());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SelectTab<T>(Func<T> constructor) where T : BaseTabSettings{
|
this.buttonHeight = BrowserUtils.Scale(39, this.GetDPIScale()) | 1;
|
||||||
BaseTabSettings control;
|
|
||||||
|
|
||||||
if (tabs.TryGetValue(typeof(T), out control)){
|
AddButton("General", () => new TabSettingsGeneral(updates));
|
||||||
tabPanel.ReplaceContent(control);
|
AddButton("Notifications", () => new TabSettingsNotifications(browser.CreateNotificationForm(false)));
|
||||||
}
|
AddButton("Sounds", () => new TabSettingsSounds());
|
||||||
else{
|
AddButton("Advanced", () => new TabSettingsAdvanced(browser.ReinjectCustomCSS));
|
||||||
control = tabs[typeof(T)] = constructor();
|
|
||||||
control.Ready = true;
|
SelectTab(tabs[startTab ?? typeof(TabSettingsGeneral)]);
|
||||||
tabPanel.ReplaceContent(control);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
private void FormSettings_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
Program.UserConfig.Save();
|
foreach(SettingsTab tab in tabs.Values){
|
||||||
|
if (tab.IsInitialized){
|
||||||
|
tab.Control.OnClosing();
|
||||||
|
tab.Control.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach(BaseTabSettings control in tabs.Values){
|
Program.UserConfig.Save();
|
||||||
control.Dispose();
|
browser.ResumeNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnManageOptions_Click(object sender, EventArgs e){
|
||||||
|
using(DialogSettingsManage dialog = new DialogSettingsManage(plugins)){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK && dialog.ShouldReloadUI){
|
||||||
|
foreach(SettingsTab tab in tabs.Values){
|
||||||
|
tab.Control = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectTab(currentTab);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +67,95 @@ namespace TweetDck.Core.Other{
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadUI(){
|
private void AddButton<T>(string title, Func<T> constructor) where T : BaseTabSettings{
|
||||||
tabs.Clear();
|
FlatButton btn = new FlatButton{
|
||||||
tabPanel.Content.Controls.Clear();
|
BackColor = SystemColors.Control,
|
||||||
tabPanel.ActiveButton.Callback();
|
FlatStyle = FlatStyle.Flat,
|
||||||
|
Location = new Point(0, (buttonHeight+1)*(panelButtons.Controls.Count/2)),
|
||||||
|
Margin = new Padding(0),
|
||||||
|
Size = new Size(panelButtons.Width, buttonHeight),
|
||||||
|
Text = title,
|
||||||
|
UseVisualStyleBackColor = true
|
||||||
|
};
|
||||||
|
|
||||||
|
btn.FlatAppearance.BorderSize = 0;
|
||||||
|
btn.FlatAppearance.MouseDownBackColor = Color.FromArgb(179, 213, 232);
|
||||||
|
btn.FlatAppearance.MouseOverBackColor = Color.FromArgb(216, 230, 237);
|
||||||
|
|
||||||
|
panelButtons.Controls.Add(btn);
|
||||||
|
|
||||||
|
panelButtons.Controls.Add(new Panel{
|
||||||
|
BackColor = Color.DimGray,
|
||||||
|
Location = new Point(0, panelButtons.Controls[panelButtons.Controls.Count-1].Location.Y+buttonHeight),
|
||||||
|
Margin = new Padding(0),
|
||||||
|
Size = new Size(panelButtons.Width, 1)
|
||||||
|
});
|
||||||
|
|
||||||
|
tabs.Add(typeof(T), new SettingsTab(btn, constructor));
|
||||||
|
|
||||||
|
btn.Click += (sender, args) => SelectTab<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectTab<T>() where T : BaseTabSettings{
|
||||||
|
SelectTab(tabs[typeof(T)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectTab(SettingsTab tab){
|
||||||
|
if (currentTab != null){
|
||||||
|
currentTab.Button.BackColor = SystemColors.Control;
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Button.BackColor = tab.Button.FlatAppearance.MouseDownBackColor;
|
||||||
|
|
||||||
|
if (!tab.IsInitialized){
|
||||||
|
foreach(Control control in tab.Control.InteractiveControls){
|
||||||
|
if (control is ComboBox){
|
||||||
|
control.MouseLeave += control_MouseLeave;
|
||||||
|
}
|
||||||
|
else if (control is TrackBar){
|
||||||
|
control.MouseWheel += control_MouseWheel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Control.OnReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
panelContents.SuspendLayout();
|
||||||
|
panelContents.VerticalScroll.Value = 0; // https://gfycat.com/GrotesqueTastyAstarte
|
||||||
|
panelContents.Controls.Clear();
|
||||||
|
panelContents.Controls.Add(tab.Control);
|
||||||
|
panelContents.ResumeLayout(true);
|
||||||
|
panelContents.Focus();
|
||||||
|
|
||||||
|
currentTab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void control_MouseLeave(object sender, EventArgs e){
|
||||||
|
panelContents.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void control_MouseWheel(object sender, MouseEventArgs e){
|
||||||
|
((HandledMouseEventArgs)e).Handled = true;
|
||||||
|
panelContents.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SettingsTab{
|
||||||
|
public Button Button { get; }
|
||||||
|
|
||||||
|
public BaseTabSettings Control{
|
||||||
|
get => control ?? (control = constructor());
|
||||||
|
set => control = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsInitialized => control != null;
|
||||||
|
|
||||||
|
private readonly Func<BaseTabSettings> constructor;
|
||||||
|
private BaseTabSettings control;
|
||||||
|
|
||||||
|
public SettingsTab(Button button, Func<BaseTabSettings> constructor){
|
||||||
|
this.Button = button;
|
||||||
|
this.constructor = constructor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
||||||
27
Core/Other/Management/BrowserProcesses.cs
Normal file
27
Core/Other/Management/BrowserProcesses.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using CefSharp;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Management{
|
||||||
|
static class BrowserProcesses{
|
||||||
|
private static readonly Dictionary<int, int> PIDs = new Dictionary<int, int>();
|
||||||
|
|
||||||
|
public static void Link(int identifier, int pid){
|
||||||
|
PIDs[identifier] = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Forget(int identifier){
|
||||||
|
PIDs.Remove(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process FindProcess(IBrowser browser){
|
||||||
|
if (PIDs.TryGetValue(browser.Identifier, out int pid) && WindowsUtils.IsChildProcess(pid)){ // child process is checked in two places for safety
|
||||||
|
return Process.GetProcessById(pid);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
91
Core/Other/Management/MemoryUsageTracker.cs
Normal file
91
Core/Other/Management/MemoryUsageTracker.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using CefSharp;
|
||||||
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Management{
|
||||||
|
sealed class MemoryUsageTracker : IDisposable{
|
||||||
|
private const int IntervalMemoryCheck = 60000*30; // 30 minutes
|
||||||
|
private const int IntervalCleanupAttempt = 60000*5; // 5 minutes
|
||||||
|
|
||||||
|
private readonly string script;
|
||||||
|
private readonly Timer timer;
|
||||||
|
private Form owner;
|
||||||
|
private IBrowser browser;
|
||||||
|
|
||||||
|
private long threshold;
|
||||||
|
private bool needsCleanup;
|
||||||
|
|
||||||
|
public MemoryUsageTracker(string cleanupFunctionName){
|
||||||
|
this.script = $"window.{cleanupFunctionName} && window.{cleanupFunctionName}()";
|
||||||
|
|
||||||
|
this.timer = new Timer{ Interval = IntervalMemoryCheck };
|
||||||
|
this.timer.Elapsed += timer_Elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(Form owner, IBrowser browser, int thresholdMB){
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
this.owner = owner;
|
||||||
|
this.browser = browser;
|
||||||
|
this.threshold = thresholdMB*1024L*1024L;
|
||||||
|
this.timer.SynchronizingObject = owner;
|
||||||
|
this.timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(){
|
||||||
|
timer.Stop();
|
||||||
|
timer.SynchronizingObject = null;
|
||||||
|
owner = null;
|
||||||
|
browser = null;
|
||||||
|
SetNeedsCleanup(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
timer.SynchronizingObject = null;
|
||||||
|
timer.Dispose();
|
||||||
|
owner = null;
|
||||||
|
browser = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetNeedsCleanup(bool value){
|
||||||
|
if (needsCleanup != value){
|
||||||
|
needsCleanup = value;
|
||||||
|
timer.Interval = value ? IntervalCleanupAttempt : IntervalMemoryCheck; // restarts timer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timer_Elapsed(object sender, ElapsedEventArgs e){
|
||||||
|
if (owner == null || browser == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsCleanup){
|
||||||
|
if (!owner.ContainsFocus){
|
||||||
|
using(IFrame frame = browser.MainFrame){
|
||||||
|
frame.EvaluateScriptAsync(script).ContinueWith(task => {
|
||||||
|
JavascriptResponse response = task.Result;
|
||||||
|
|
||||||
|
if (response.Success && (response.Result as bool? ?? false)){
|
||||||
|
SetNeedsCleanup(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
try{
|
||||||
|
using(Process process = BrowserProcesses.FindProcess(browser)){
|
||||||
|
if (process?.PrivateMemorySize64 > threshold){
|
||||||
|
SetNeedsCleanup(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
// ignore I guess?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
175
Core/Other/Management/VideoPlayer.cs
Normal file
175
Core/Other/Management/VideoPlayer.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetLib.Communication;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Management{
|
||||||
|
sealed class VideoPlayer : IDisposable{
|
||||||
|
private readonly string PlayerExe = Path.Combine(Program.ProgramPath, "TweetDuck.Video.exe");
|
||||||
|
|
||||||
|
public bool Running{
|
||||||
|
get{
|
||||||
|
if (currentProcess == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProcess.Refresh();
|
||||||
|
return !currentProcess.HasExited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler ProcessExited;
|
||||||
|
|
||||||
|
private readonly Form owner;
|
||||||
|
private string lastUrl;
|
||||||
|
|
||||||
|
private Process currentProcess;
|
||||||
|
private DuplexPipe.Server currentPipe;
|
||||||
|
private bool isClosing;
|
||||||
|
|
||||||
|
public VideoPlayer(Form owner){
|
||||||
|
this.owner = owner;
|
||||||
|
this.owner.FormClosing += owner_FormClosing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Launch(string url){
|
||||||
|
if (Running){
|
||||||
|
Destroy();
|
||||||
|
isClosing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUrl = url;
|
||||||
|
|
||||||
|
try{
|
||||||
|
currentPipe = DuplexPipe.CreateServer();
|
||||||
|
currentPipe.DataIn += currentPipe_DataIn;
|
||||||
|
|
||||||
|
if ((currentProcess = Process.Start(new ProcessStartInfo{
|
||||||
|
FileName = PlayerExe,
|
||||||
|
Arguments = $"{owner.Handle} {Program.UserConfig.VideoPlayerVolume} \"{url}\" \"{currentPipe.GenerateToken()}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true
|
||||||
|
})) != null){
|
||||||
|
currentProcess.EnableRaisingEvents = true;
|
||||||
|
currentProcess.Exited += process_Exited;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
currentProcess.BeginOutputReadLine();
|
||||||
|
currentProcess.OutputDataReceived += (sender, args) => Debug.WriteLine("VideoPlayer: "+args.Data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPipe.DisposeToken();
|
||||||
|
}catch(Exception e){
|
||||||
|
Program.Reporter.HandleException("Video Playback Error", "Error launching video player.", true, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TogglePause(){
|
||||||
|
currentPipe?.Write("pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void currentPipe_DataIn(object sender, DuplexPipe.PipeReadEventArgs e){
|
||||||
|
owner.InvokeSafe(() => {
|
||||||
|
switch(e.Key){
|
||||||
|
case "vol":
|
||||||
|
if (int.TryParse(e.Data, out int volume) && volume != Program.UserConfig.VideoPlayerVolume){
|
||||||
|
Program.UserConfig.VideoPlayerVolume = volume;
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "rip":
|
||||||
|
currentPipe.Dispose();
|
||||||
|
currentPipe = null;
|
||||||
|
|
||||||
|
currentProcess.Dispose();
|
||||||
|
currentProcess = null;
|
||||||
|
|
||||||
|
isClosing = false;
|
||||||
|
TriggerProcessExitEventUnsafe();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close(){
|
||||||
|
if (currentProcess != null){
|
||||||
|
if (isClosing){
|
||||||
|
Destroy();
|
||||||
|
isClosing = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
isClosing = true;
|
||||||
|
currentProcess.Exited -= process_Exited;
|
||||||
|
currentPipe.Write("die");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose(){
|
||||||
|
ProcessExited = null;
|
||||||
|
|
||||||
|
isClosing = true;
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Destroy(){
|
||||||
|
if (currentProcess != null){
|
||||||
|
try{
|
||||||
|
currentProcess.Kill();
|
||||||
|
}catch{
|
||||||
|
// kill me instead then
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProcess.Dispose();
|
||||||
|
currentProcess = null;
|
||||||
|
|
||||||
|
currentPipe.Dispose();
|
||||||
|
currentPipe = null;
|
||||||
|
|
||||||
|
TriggerProcessExitEventUnsafe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void owner_FormClosing(object sender, FormClosingEventArgs e){
|
||||||
|
if (currentProcess != null){
|
||||||
|
currentProcess.Exited -= process_Exited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void process_Exited(object sender, EventArgs e){
|
||||||
|
switch(currentProcess.ExitCode){
|
||||||
|
case 3: // CODE_LAUNCH_FAIL
|
||||||
|
if (FormMessage.Error("Video Playback Error", "Error launching video player, this may be caused by missing Windows Media Player. Do you want to open the video in a browser?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
BrowserUtils.OpenExternalBrowser(lastUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // CODE_MEDIA_ERROR
|
||||||
|
if (FormMessage.Error("Video Playback Error", "The video could not be loaded, most likely due to unknown format. Do you want to open the video in a browser?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
BrowserUtils.OpenExternalBrowser(lastUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProcess.Dispose();
|
||||||
|
currentProcess = null;
|
||||||
|
|
||||||
|
currentPipe.Dispose();
|
||||||
|
currentPipe = null;
|
||||||
|
|
||||||
|
owner.InvokeAsyncSafe(TriggerProcessExitEventUnsafe);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TriggerProcessExitEventUnsafe(){
|
||||||
|
ProcessExited?.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Core/Other/Settings/BaseTabSettings.Designer.cs
generated
3
Core/Other/Settings/BaseTabSettings.Designer.cs
generated
@@ -1,3 +0,0 @@
|
|||||||
namespace TweetDck.Core.Other.Settings{
|
|
||||||
partial class BaseTabSettings{}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,31 @@
|
|||||||
using System.Windows.Forms;
|
using System.Collections.Generic;
|
||||||
using TweetDck.Configuration;
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Configuration;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
partial class BaseTabSettings : UserControl{
|
class BaseTabSettings : UserControl{
|
||||||
protected static UserConfig Config{
|
protected static UserConfig Config => Program.UserConfig;
|
||||||
|
|
||||||
|
public IEnumerable<Control> InteractiveControls{
|
||||||
get{
|
get{
|
||||||
return Program.UserConfig;
|
foreach(Panel panel in Controls.OfType<Panel>()){
|
||||||
|
foreach(Control control in panel.Controls){
|
||||||
|
yield return control;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Ready { get; set; }
|
|
||||||
|
|
||||||
public BaseTabSettings(){
|
public BaseTabSettings(){
|
||||||
Padding = new Padding(6);
|
Padding = new Padding(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void OnReady(){}
|
||||||
|
public virtual void OnClosing(){}
|
||||||
|
|
||||||
protected static void PromptRestart(){
|
protected static void PromptRestart(){
|
||||||
if (MessageBox.Show("The application must restart for the setting to take place. Do you want to restart now?", Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes){
|
if (FormMessage.Information("TweetDuck Options", "The application must restart for the option to take place. Do you want to restart now?", FormMessage.Yes, FormMessage.No)){
|
||||||
Program.Restart();
|
Program.Restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other.Settings.Dialogs {
|
namespace TweetDuck.Core.Other.Settings.Dialogs {
|
||||||
partial class DialogSettingsCSS {
|
partial class DialogSettingsCSS {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
|
this.textBoxBrowserCSS = new System.Windows.Forms.TextBox();
|
||||||
this.btnCancel = new System.Windows.Forms.Button();
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
this.btnApply = new System.Windows.Forms.Button();
|
this.btnApply = new System.Windows.Forms.Button();
|
||||||
@@ -31,6 +32,8 @@
|
|||||||
this.labelNotification = new System.Windows.Forms.Label();
|
this.labelNotification = new System.Windows.Forms.Label();
|
||||||
this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
|
this.textBoxNotificationCSS = new System.Windows.Forms.TextBox();
|
||||||
this.labelWarning = new System.Windows.Forms.Label();
|
this.labelWarning = new System.Windows.Forms.Label();
|
||||||
|
this.btnOpenWiki = new System.Windows.Forms.Button();
|
||||||
|
this.timerTestBrowser = new System.Windows.Forms.Timer(this.components);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||||
this.splitContainer.Panel1.SuspendLayout();
|
this.splitContainer.Panel1.SuspendLayout();
|
||||||
this.splitContainer.Panel2.SuspendLayout();
|
this.splitContainer.Panel2.SuspendLayout();
|
||||||
@@ -39,18 +42,17 @@
|
|||||||
//
|
//
|
||||||
// textBoxBrowserCSS
|
// textBoxBrowserCSS
|
||||||
//
|
//
|
||||||
this.textBoxBrowserCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.textBoxBrowserCSS.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.textBoxBrowserCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.textBoxBrowserCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.textBoxBrowserCSS.Location = new System.Drawing.Point(0, 16);
|
this.textBoxBrowserCSS.Location = new System.Drawing.Point(0, 16);
|
||||||
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
this.textBoxBrowserCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
this.textBoxBrowserCSS.Multiline = true;
|
this.textBoxBrowserCSS.Multiline = true;
|
||||||
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
|
this.textBoxBrowserCSS.Name = "textBoxBrowserCSS";
|
||||||
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.textBoxBrowserCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.textBoxBrowserCSS.Size = new System.Drawing.Size(373, 253);
|
this.textBoxBrowserCSS.Size = new System.Drawing.Size(378, 253);
|
||||||
this.textBoxBrowserCSS.TabIndex = 0;
|
this.textBoxBrowserCSS.TabIndex = 1;
|
||||||
this.textBoxBrowserCSS.WordWrap = false;
|
this.textBoxBrowserCSS.WordWrap = false;
|
||||||
|
this.textBoxBrowserCSS.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBoxBrowserCSS_KeyUp);
|
||||||
//
|
//
|
||||||
// btnCancel
|
// btnCancel
|
||||||
//
|
//
|
||||||
@@ -59,7 +61,7 @@
|
|||||||
this.btnCancel.Name = "btnCancel";
|
this.btnCancel.Name = "btnCancel";
|
||||||
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
this.btnCancel.TabIndex = 1;
|
this.btnCancel.TabIndex = 2;
|
||||||
this.btnCancel.Text = "Cancel";
|
this.btnCancel.Text = "Cancel";
|
||||||
this.btnCancel.UseVisualStyleBackColor = true;
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
@@ -71,7 +73,7 @@
|
|||||||
this.btnApply.Name = "btnApply";
|
this.btnApply.Name = "btnApply";
|
||||||
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
this.btnApply.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
this.btnApply.Size = new System.Drawing.Size(56, 23);
|
this.btnApply.Size = new System.Drawing.Size(56, 23);
|
||||||
this.btnApply.TabIndex = 2;
|
this.btnApply.TabIndex = 1;
|
||||||
this.btnApply.Text = "Apply";
|
this.btnApply.Text = "Apply";
|
||||||
this.btnApply.UseVisualStyleBackColor = true;
|
this.btnApply.UseVisualStyleBackColor = true;
|
||||||
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||||
@@ -96,9 +98,9 @@
|
|||||||
this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS);
|
this.splitContainer.Panel2.Controls.Add(this.textBoxNotificationCSS);
|
||||||
this.splitContainer.Panel2MinSize = 64;
|
this.splitContainer.Panel2MinSize = 64;
|
||||||
this.splitContainer.Size = new System.Drawing.Size(760, 269);
|
this.splitContainer.Size = new System.Drawing.Size(760, 269);
|
||||||
this.splitContainer.SplitterDistance = 373;
|
this.splitContainer.SplitterDistance = 378;
|
||||||
this.splitContainer.SplitterWidth = 5;
|
this.splitContainer.SplitterWidth = 5;
|
||||||
this.splitContainer.TabIndex = 5;
|
this.splitContainer.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// labelBrowser
|
// labelBrowser
|
||||||
//
|
//
|
||||||
@@ -107,7 +109,7 @@
|
|||||||
this.labelBrowser.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
this.labelBrowser.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
this.labelBrowser.Name = "labelBrowser";
|
this.labelBrowser.Name = "labelBrowser";
|
||||||
this.labelBrowser.Size = new System.Drawing.Size(45, 13);
|
this.labelBrowser.Size = new System.Drawing.Size(45, 13);
|
||||||
this.labelBrowser.TabIndex = 1;
|
this.labelBrowser.TabIndex = 0;
|
||||||
this.labelBrowser.Text = "Browser";
|
this.labelBrowser.Text = "Browser";
|
||||||
//
|
//
|
||||||
// labelNotification
|
// labelNotification
|
||||||
@@ -117,21 +119,19 @@
|
|||||||
this.labelNotification.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
this.labelNotification.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
this.labelNotification.Name = "labelNotification";
|
this.labelNotification.Name = "labelNotification";
|
||||||
this.labelNotification.Size = new System.Drawing.Size(60, 13);
|
this.labelNotification.Size = new System.Drawing.Size(60, 13);
|
||||||
this.labelNotification.TabIndex = 2;
|
this.labelNotification.TabIndex = 0;
|
||||||
this.labelNotification.Text = "Notification";
|
this.labelNotification.Text = "Notification";
|
||||||
//
|
//
|
||||||
// textBoxNotificationCSS
|
// textBoxNotificationCSS
|
||||||
//
|
//
|
||||||
this.textBoxNotificationCSS.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.textBoxNotificationCSS.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.textBoxNotificationCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
this.textBoxNotificationCSS.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.textBoxNotificationCSS.Location = new System.Drawing.Point(0, 16);
|
this.textBoxNotificationCSS.Location = new System.Drawing.Point(0, 16);
|
||||||
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
this.textBoxNotificationCSS.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
|
||||||
this.textBoxNotificationCSS.Multiline = true;
|
this.textBoxNotificationCSS.Multiline = true;
|
||||||
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
|
this.textBoxNotificationCSS.Name = "textBoxNotificationCSS";
|
||||||
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
this.textBoxNotificationCSS.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
this.textBoxNotificationCSS.Size = new System.Drawing.Size(378, 253);
|
this.textBoxNotificationCSS.Size = new System.Drawing.Size(377, 253);
|
||||||
this.textBoxNotificationCSS.TabIndex = 1;
|
this.textBoxNotificationCSS.TabIndex = 1;
|
||||||
this.textBoxNotificationCSS.WordWrap = false;
|
this.textBoxNotificationCSS.WordWrap = false;
|
||||||
//
|
//
|
||||||
@@ -139,22 +139,40 @@
|
|||||||
//
|
//
|
||||||
this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.labelWarning.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.labelWarning.AutoSize = true;
|
this.labelWarning.AutoSize = true;
|
||||||
this.labelWarning.Location = new System.Drawing.Point(9, 292);
|
this.labelWarning.Location = new System.Drawing.Point(91, 292);
|
||||||
this.labelWarning.Name = "labelWarning";
|
this.labelWarning.Name = "labelWarning";
|
||||||
this.labelWarning.Size = new System.Drawing.Size(341, 13);
|
this.labelWarning.Size = new System.Drawing.Size(341, 13);
|
||||||
this.labelWarning.TabIndex = 6;
|
this.labelWarning.TabIndex = 3;
|
||||||
this.labelWarning.Text = "The code is not validated, please make sure there are no syntax errors.";
|
this.labelWarning.Text = "The code is not validated, please make sure there are no syntax errors.";
|
||||||
//
|
//
|
||||||
|
// btnOpenWiki
|
||||||
|
//
|
||||||
|
this.btnOpenWiki.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
|
this.btnOpenWiki.Location = new System.Drawing.Point(12, 287);
|
||||||
|
this.btnOpenWiki.Name = "btnOpenWiki";
|
||||||
|
this.btnOpenWiki.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnOpenWiki.Size = new System.Drawing.Size(73, 23);
|
||||||
|
this.btnOpenWiki.TabIndex = 4;
|
||||||
|
this.btnOpenWiki.Text = "Open Wiki";
|
||||||
|
this.btnOpenWiki.UseVisualStyleBackColor = true;
|
||||||
|
this.btnOpenWiki.Click += new System.EventHandler(this.btnOpenWiki_Click);
|
||||||
|
//
|
||||||
|
// timerTestBrowser
|
||||||
|
//
|
||||||
|
this.timerTestBrowser.Interval = 500;
|
||||||
|
this.timerTestBrowser.Tick += new System.EventHandler(this.timerTestBrowser_Tick);
|
||||||
|
//
|
||||||
// DialogSettingsCSS
|
// DialogSettingsCSS
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(784, 322);
|
this.ClientSize = new System.Drawing.Size(784, 322);
|
||||||
|
this.Controls.Add(this.btnOpenWiki);
|
||||||
this.Controls.Add(this.labelWarning);
|
this.Controls.Add(this.labelWarning);
|
||||||
this.Controls.Add(this.splitContainer);
|
this.Controls.Add(this.splitContainer);
|
||||||
this.Controls.Add(this.btnApply);
|
this.Controls.Add(this.btnApply);
|
||||||
this.Controls.Add(this.btnCancel);
|
this.Controls.Add(this.btnCancel);
|
||||||
this.MinimumSize = new System.Drawing.Size(500, 160);
|
this.MinimumSize = new System.Drawing.Size(600, 160);
|
||||||
this.Name = "DialogSettingsCSS";
|
this.Name = "DialogSettingsCSS";
|
||||||
this.ShowIcon = false;
|
this.ShowIcon = false;
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
@@ -179,5 +197,7 @@
|
|||||||
private System.Windows.Forms.Label labelBrowser;
|
private System.Windows.Forms.Label labelBrowser;
|
||||||
private System.Windows.Forms.Label labelNotification;
|
private System.Windows.Forms.Label labelNotification;
|
||||||
private System.Windows.Forms.Label labelWarning;
|
private System.Windows.Forms.Label labelWarning;
|
||||||
|
private System.Windows.Forms.Button btnOpenWiki;
|
||||||
|
private System.Windows.Forms.Timer timerTestBrowser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings.Dialogs{
|
namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||||
sealed partial class DialogSettingsCSS : Form{
|
sealed partial class DialogSettingsCSS : Form{
|
||||||
public string BrowserCSS{
|
public string BrowserCSS => textBoxBrowserCSS.Text;
|
||||||
get{
|
public string NotificationCSS => textBoxNotificationCSS.Text;
|
||||||
return textBoxBrowserCSS.Text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NotificationCSS{
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
get{
|
|
||||||
return textBoxNotificationCSS.Text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogSettingsCSS(){
|
public DialogSettingsCSS(Action<string> reinjectBrowserCSS){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName+" Settings - CSS";
|
Text = Program.BrandName+" Options - CSS";
|
||||||
|
|
||||||
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
|
|
||||||
textBoxBrowserCSS.EnableMultilineShortcuts();
|
textBoxBrowserCSS.EnableMultilineShortcuts();
|
||||||
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
|
textBoxBrowserCSS.Text = Program.UserConfig.CustomBrowserCSS ?? "";
|
||||||
@@ -28,6 +24,20 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
|
|||||||
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
|
textBoxNotificationCSS.Text = Program.UserConfig.CustomNotificationCSS ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void textBoxBrowserCSS_KeyUp(object sender, KeyEventArgs e){
|
||||||
|
timerTestBrowser.Stop();
|
||||||
|
timerTestBrowser.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerTestBrowser_Tick(object sender, EventArgs e){
|
||||||
|
reinjectBrowserCSS(textBoxBrowserCSS.Text);
|
||||||
|
timerTestBrowser.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOpenWiki_Click(object sender, EventArgs e){
|
||||||
|
BrowserUtils.OpenExternalBrowserUnsafe("https://github.com/chylex/TweetDuck/wiki");
|
||||||
|
}
|
||||||
|
|
||||||
private void btnApply_Click(object sender, EventArgs e){
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
Close();
|
Close();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other.Settings.Dialogs {
|
namespace TweetDuck.Core.Other.Settings.Dialogs {
|
||||||
partial class DialogSettingsCefArgs {
|
partial class DialogSettingsCefArgs {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
this.textBoxArgs.Multiline = true;
|
this.textBoxArgs.Multiline = true;
|
||||||
this.textBoxArgs.Name = "textBoxArgs";
|
this.textBoxArgs.Name = "textBoxArgs";
|
||||||
this.textBoxArgs.Size = new System.Drawing.Size(460, 193);
|
this.textBoxArgs.Size = new System.Drawing.Size(460, 193);
|
||||||
this.textBoxArgs.TabIndex = 0;
|
this.textBoxArgs.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// btnCancel
|
// btnCancel
|
||||||
//
|
//
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
this.btnCancel.Name = "btnCancel";
|
this.btnCancel.Name = "btnCancel";
|
||||||
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
this.btnCancel.TabIndex = 1;
|
this.btnCancel.TabIndex = 3;
|
||||||
this.btnCancel.Text = "Cancel";
|
this.btnCancel.Text = "Cancel";
|
||||||
this.btnCancel.UseVisualStyleBackColor = true;
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
@@ -69,12 +69,11 @@
|
|||||||
// btnHelp
|
// btnHelp
|
||||||
//
|
//
|
||||||
this.btnHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.btnHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.btnHelp.AutoSize = true;
|
|
||||||
this.btnHelp.Location = new System.Drawing.Point(12, 227);
|
this.btnHelp.Location = new System.Drawing.Point(12, 227);
|
||||||
this.btnHelp.Name = "btnHelp";
|
this.btnHelp.Name = "btnHelp";
|
||||||
this.btnHelp.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
this.btnHelp.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
this.btnHelp.Size = new System.Drawing.Size(124, 23);
|
this.btnHelp.Size = new System.Drawing.Size(124, 23);
|
||||||
this.btnHelp.TabIndex = 3;
|
this.btnHelp.TabIndex = 4;
|
||||||
this.btnHelp.Text = "List of Chromium Args";
|
this.btnHelp.Text = "List of Chromium Args";
|
||||||
this.btnHelp.UseVisualStyleBackColor = true;
|
this.btnHelp.UseVisualStyleBackColor = true;
|
||||||
this.btnHelp.Click += new System.EventHandler(this.btnHelp_Click);
|
this.btnHelp.Click += new System.EventHandler(this.btnHelp_Click);
|
||||||
@@ -86,7 +85,7 @@
|
|||||||
this.labelWarning.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
this.labelWarning.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
||||||
this.labelWarning.Name = "labelWarning";
|
this.labelWarning.Name = "labelWarning";
|
||||||
this.labelWarning.Size = new System.Drawing.Size(423, 13);
|
this.labelWarning.Size = new System.Drawing.Size(423, 13);
|
||||||
this.labelWarning.TabIndex = 4;
|
this.labelWarning.TabIndex = 0;
|
||||||
this.labelWarning.Text = "Warning: Some arguments may cause the program to stop working, edit at your own r" +
|
this.labelWarning.Text = "Warning: Some arguments may cause the program to stop working, edit at your own r" +
|
||||||
"isk.";
|
"isk.";
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings.Dialogs{
|
namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||||
sealed partial class DialogSettingsCefArgs : Form{
|
sealed partial class DialogSettingsCefArgs : Form{
|
||||||
public string CefArgs{
|
public string CefArgs => textBoxArgs.Text;
|
||||||
get{
|
|
||||||
return textBoxArgs.Text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DialogSettingsCefArgs(){
|
public DialogSettingsCefArgs(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Text = Program.BrandName+" Settings - CEF Arguments";
|
Text = Program.BrandName+" Options - CEF Arguments";
|
||||||
|
|
||||||
textBoxArgs.EnableMultilineShortcuts();
|
textBoxArgs.EnableMultilineShortcuts();
|
||||||
textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? "";
|
textBoxArgs.Text = Program.UserConfig.CustomCefArgs ?? "";
|
||||||
@@ -22,7 +19,7 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void btnHelp_Click(object sender, EventArgs e){
|
private void btnHelp_Click(object sender, EventArgs e){
|
||||||
BrowserUtils.OpenExternalBrowser("http://peter.sh/experiments/chromium-command-line-switches/");
|
BrowserUtils.OpenExternalBrowserUnsafe("http://peter.sh/experiments/chromium-command-line-switches/");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnApply_Click(object sender, EventArgs e){
|
private void btnApply_Click(object sender, EventArgs e){
|
||||||
@@ -34,10 +31,10 @@ namespace TweetDck.Core.Other.Settings.Dialogs{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = CommandLineArgsParser.ReadCefArguments(CefArgs).Count;
|
int count = CommandLineArgs.ReadCefArguments(CefArgs).Count;
|
||||||
string prompt = count == 0 && !string.IsNullOrWhiteSpace(prevArgs) ? "All arguments will be removed from the settings. Continue?" : count+(count == 1 ? " argument" : " arguments")+" will be added to the settings. Continue?";
|
string prompt = count == 0 && !string.IsNullOrWhiteSpace(prevArgs) ? "All current arguments will be removed. Continue?" : count+(count == 1 ? " argument was" : " arguments were")+" detected. Continue?";
|
||||||
|
|
||||||
if (MessageBox.Show(prompt, "Confirm CEF Arguments", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK){
|
if (FormMessage.Question("Confirm CEF Arguments", prompt, FormMessage.OK, FormMessage.Cancel)){
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
201
Core/Other/Settings/Dialogs/DialogSettingsManage.Designer.cs
generated
Normal file
201
Core/Other/Settings/Dialogs/DialogSettingsManage.Designer.cs
generated
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
namespace TweetDuck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsManage {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnContinue = new System.Windows.Forms.Button();
|
||||||
|
this.cbConfig = new System.Windows.Forms.CheckBox();
|
||||||
|
this.cbSession = new System.Windows.Forms.CheckBox();
|
||||||
|
this.cbPluginData = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.panelExport = new System.Windows.Forms.Panel();
|
||||||
|
this.panelDecision = new System.Windows.Forms.Panel();
|
||||||
|
this.radioReset = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioExport = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioImport = new System.Windows.Forms.RadioButton();
|
||||||
|
this.panelExport.SuspendLayout();
|
||||||
|
this.panelDecision.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(176, 97);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 4;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnContinue
|
||||||
|
//
|
||||||
|
this.btnContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnContinue.AutoSize = true;
|
||||||
|
this.btnContinue.Enabled = false;
|
||||||
|
this.btnContinue.Location = new System.Drawing.Point(125, 97);
|
||||||
|
this.btnContinue.Name = "btnContinue";
|
||||||
|
this.btnContinue.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnContinue.Size = new System.Drawing.Size(45, 23);
|
||||||
|
this.btnContinue.TabIndex = 3;
|
||||||
|
this.btnContinue.Text = "Next";
|
||||||
|
this.btnContinue.UseVisualStyleBackColor = true;
|
||||||
|
this.btnContinue.Click += new System.EventHandler(this.btnContinue_Click);
|
||||||
|
//
|
||||||
|
// cbConfig
|
||||||
|
//
|
||||||
|
this.cbConfig.AutoSize = true;
|
||||||
|
this.cbConfig.Location = new System.Drawing.Point(0, 3);
|
||||||
|
this.cbConfig.Name = "cbConfig";
|
||||||
|
this.cbConfig.Size = new System.Drawing.Size(104, 17);
|
||||||
|
this.cbConfig.TabIndex = 0;
|
||||||
|
this.cbConfig.Text = "Program Options";
|
||||||
|
this.toolTip.SetToolTip(this.cbConfig, "Interface, notification, and update options.");
|
||||||
|
this.cbConfig.UseVisualStyleBackColor = true;
|
||||||
|
this.cbConfig.CheckedChanged += new System.EventHandler(this.cbConfig_CheckedChanged);
|
||||||
|
//
|
||||||
|
// cbSession
|
||||||
|
//
|
||||||
|
this.cbSession.AutoSize = true;
|
||||||
|
this.cbSession.Location = new System.Drawing.Point(0, 27);
|
||||||
|
this.cbSession.Name = "cbSession";
|
||||||
|
this.cbSession.Size = new System.Drawing.Size(92, 17);
|
||||||
|
this.cbSession.TabIndex = 1;
|
||||||
|
this.cbSession.Text = "Login Session";
|
||||||
|
this.toolTip.SetToolTip(this.cbSession, "A token that allows logging into the\r\ncurrent TweetDeck account.");
|
||||||
|
this.cbSession.UseVisualStyleBackColor = true;
|
||||||
|
this.cbSession.CheckedChanged += new System.EventHandler(this.cbSession_CheckedChanged);
|
||||||
|
//
|
||||||
|
// cbPluginData
|
||||||
|
//
|
||||||
|
this.cbPluginData.AutoSize = true;
|
||||||
|
this.cbPluginData.Location = new System.Drawing.Point(0, 51);
|
||||||
|
this.cbPluginData.Name = "cbPluginData";
|
||||||
|
this.cbPluginData.Size = new System.Drawing.Size(81, 17);
|
||||||
|
this.cbPluginData.TabIndex = 2;
|
||||||
|
this.cbPluginData.Text = "Plugin Data";
|
||||||
|
this.toolTip.SetToolTip(this.cbPluginData, "Data files generated by plugins.\r\nDoes not include the plugins themselves.");
|
||||||
|
this.cbPluginData.UseVisualStyleBackColor = true;
|
||||||
|
this.cbPluginData.CheckedChanged += new System.EventHandler(this.cbPluginData_CheckedChanged);
|
||||||
|
//
|
||||||
|
// panelExport
|
||||||
|
//
|
||||||
|
this.panelExport.Controls.Add(this.cbConfig);
|
||||||
|
this.panelExport.Controls.Add(this.cbPluginData);
|
||||||
|
this.panelExport.Controls.Add(this.cbSession);
|
||||||
|
this.panelExport.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.panelExport.Name = "panelExport";
|
||||||
|
this.panelExport.Size = new System.Drawing.Size(220, 79);
|
||||||
|
this.panelExport.TabIndex = 5;
|
||||||
|
this.panelExport.Visible = false;
|
||||||
|
//
|
||||||
|
// panelDecision
|
||||||
|
//
|
||||||
|
this.panelDecision.Controls.Add(this.radioReset);
|
||||||
|
this.panelDecision.Controls.Add(this.radioExport);
|
||||||
|
this.panelDecision.Controls.Add(this.radioImport);
|
||||||
|
this.panelDecision.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.panelDecision.Name = "panelDecision";
|
||||||
|
this.panelDecision.Size = new System.Drawing.Size(220, 79);
|
||||||
|
this.panelDecision.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// radioReset
|
||||||
|
//
|
||||||
|
this.radioReset.AutoSize = true;
|
||||||
|
this.radioReset.Location = new System.Drawing.Point(3, 49);
|
||||||
|
this.radioReset.Name = "radioReset";
|
||||||
|
this.radioReset.Size = new System.Drawing.Size(104, 17);
|
||||||
|
this.radioReset.TabIndex = 2;
|
||||||
|
this.radioReset.TabStop = true;
|
||||||
|
this.radioReset.Text = "Restore Defaults";
|
||||||
|
this.radioReset.UseVisualStyleBackColor = true;
|
||||||
|
this.radioReset.CheckedChanged += new System.EventHandler(this.radioDecision_CheckedChanged);
|
||||||
|
//
|
||||||
|
// radioExport
|
||||||
|
//
|
||||||
|
this.radioExport.AutoSize = true;
|
||||||
|
this.radioExport.Location = new System.Drawing.Point(3, 26);
|
||||||
|
this.radioExport.Name = "radioExport";
|
||||||
|
this.radioExport.Size = new System.Drawing.Size(87, 17);
|
||||||
|
this.radioExport.TabIndex = 1;
|
||||||
|
this.radioExport.TabStop = true;
|
||||||
|
this.radioExport.Text = "Export Profile";
|
||||||
|
this.radioExport.UseVisualStyleBackColor = true;
|
||||||
|
this.radioExport.CheckedChanged += new System.EventHandler(this.radioDecision_CheckedChanged);
|
||||||
|
//
|
||||||
|
// radioImport
|
||||||
|
//
|
||||||
|
this.radioImport.AutoSize = true;
|
||||||
|
this.radioImport.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.radioImport.Name = "radioImport";
|
||||||
|
this.radioImport.Size = new System.Drawing.Size(86, 17);
|
||||||
|
this.radioImport.TabIndex = 0;
|
||||||
|
this.radioImport.TabStop = true;
|
||||||
|
this.radioImport.Text = "Import Profile";
|
||||||
|
this.radioImport.UseVisualStyleBackColor = true;
|
||||||
|
this.radioImport.CheckedChanged += new System.EventHandler(this.radioDecision_CheckedChanged);
|
||||||
|
//
|
||||||
|
// DialogSettingsManage
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(244, 132);
|
||||||
|
this.Controls.Add(this.panelDecision);
|
||||||
|
this.Controls.Add(this.panelExport);
|
||||||
|
this.Controls.Add(this.btnContinue);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.MinimumSize = new System.Drawing.Size(200, 170);
|
||||||
|
this.Name = "DialogSettingsManage";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Manage Options";
|
||||||
|
this.panelExport.ResumeLayout(false);
|
||||||
|
this.panelExport.PerformLayout();
|
||||||
|
this.panelDecision.ResumeLayout(false);
|
||||||
|
this.panelDecision.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnContinue;
|
||||||
|
private System.Windows.Forms.CheckBox cbConfig;
|
||||||
|
private System.Windows.Forms.CheckBox cbSession;
|
||||||
|
private System.Windows.Forms.CheckBox cbPluginData;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.Panel panelExport;
|
||||||
|
private System.Windows.Forms.Panel panelDecision;
|
||||||
|
private System.Windows.Forms.RadioButton radioReset;
|
||||||
|
private System.Windows.Forms.RadioButton radioExport;
|
||||||
|
private System.Windows.Forms.RadioButton radioImport;
|
||||||
|
}
|
||||||
|
}
|
||||||
170
Core/Other/Settings/Dialogs/DialogSettingsManage.cs
Normal file
170
Core/Other/Settings/Dialogs/DialogSettingsManage.cs
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Other.Settings.Export;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsManage : Form{
|
||||||
|
private enum State{
|
||||||
|
Deciding, Import, Export
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportFileFlags Flags{
|
||||||
|
get => selectedFlags;
|
||||||
|
|
||||||
|
set{
|
||||||
|
// this will call events and SetFlag, which also updates the UI
|
||||||
|
cbConfig.Checked = value.HasFlag(ExportFileFlags.Config);
|
||||||
|
cbSession.Checked = value.HasFlag(ExportFileFlags.Session);
|
||||||
|
cbPluginData.Checked = value.HasFlag(ExportFileFlags.PluginData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldReloadUI { get; private set; }
|
||||||
|
|
||||||
|
private readonly PluginManager plugins;
|
||||||
|
private State currentState;
|
||||||
|
|
||||||
|
private ExportManager importManager;
|
||||||
|
private ExportFileFlags selectedFlags = ExportFileFlags.None;
|
||||||
|
|
||||||
|
public DialogSettingsManage(PluginManager plugins){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.plugins = plugins;
|
||||||
|
this.currentState = State.Deciding;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioDecision_CheckedChanged(object sender, EventArgs e){
|
||||||
|
btnContinue.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbConfig_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.Config, cbConfig.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbSession_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.Session, cbSession.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cbPluginData_CheckedChanged(object sender, EventArgs e){
|
||||||
|
SetFlag(ExportFileFlags.PluginData, cbPluginData.Checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnContinue_Click(object sender, EventArgs e){
|
||||||
|
string file;
|
||||||
|
|
||||||
|
switch(currentState){
|
||||||
|
case State.Deciding:
|
||||||
|
// Reset
|
||||||
|
if (radioReset.Checked){
|
||||||
|
if (FormMessage.Warning("Reset TweetDuck Options", "This will reset all of your program options. Plugins will not be affected. Do you want to proceed?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
Program.ResetConfig();
|
||||||
|
|
||||||
|
ShouldReloadUI = true;
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import
|
||||||
|
else if (radioImport.Checked){
|
||||||
|
using(OpenFileDialog dialog = new OpenFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
DereferenceLinks = true,
|
||||||
|
Title = "Import TweetDuck Profile",
|
||||||
|
Filter = "TweetDuck Profile (*.tdsettings)|*.tdsettings"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = dialog.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
importManager = new ExportManager(file, plugins);
|
||||||
|
currentState = State.Import;
|
||||||
|
|
||||||
|
Text = "Import Profile";
|
||||||
|
Flags = importManager.GetImportFlags();
|
||||||
|
|
||||||
|
cbConfig.Enabled = cbConfig.Checked;
|
||||||
|
cbSession.Enabled = cbSession.Checked;
|
||||||
|
cbPluginData.Enabled = cbPluginData.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export
|
||||||
|
else if (radioExport.Checked){
|
||||||
|
currentState = State.Export;
|
||||||
|
|
||||||
|
Text = "Export Profile";
|
||||||
|
btnContinue.Text = "Export Profile";
|
||||||
|
Flags = ExportFileFlags.All & ~ExportFileFlags.Session;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue...
|
||||||
|
panelDecision.Visible = false;
|
||||||
|
panelExport.Visible = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State.Import:
|
||||||
|
if (importManager.Import(Flags)){
|
||||||
|
if (!importManager.IsRestarting){
|
||||||
|
ShouldReloadUI = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Program.Reporter.HandleException("Profile Import Error", "An exception happened while importing TweetDuck profile.", true, importManager.LastException);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State.Export:
|
||||||
|
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||||
|
AddExtension = true,
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
OverwritePrompt = true,
|
||||||
|
DefaultExt = "tdsettings",
|
||||||
|
FileName = "TweetDuck.tdsettings",
|
||||||
|
Title = "Export TweetDuck Profile",
|
||||||
|
Filter = "TweetDuck Profile (*.tdsettings)|*.tdsettings"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() != DialogResult.OK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = dialog.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Program.UserConfig.Save();
|
||||||
|
ExportManager manager = new ExportManager(file, plugins);
|
||||||
|
|
||||||
|
if (!manager.Export(Flags)){
|
||||||
|
Program.Reporter.HandleException("Profile Export Error", "An exception happened while exporting TweetDuck profile.", true, manager.LastException);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFlag(ExportFileFlags flag, bool enable){
|
||||||
|
selectedFlags = enable ? selectedFlags | flag : selectedFlags & ~flag;
|
||||||
|
btnContinue.Enabled = selectedFlags != ExportFileFlags.None;
|
||||||
|
|
||||||
|
if (currentState == State.Import){
|
||||||
|
btnContinue.Text = selectedFlags.HasFlag(ExportFileFlags.Session) ? "Import && Restart" : "Import Profile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
159
Core/Other/Settings/Dialogs/DialogSettingsRestart.Designer.cs
generated
Normal file
159
Core/Other/Settings/Dialogs/DialogSettingsRestart.Designer.cs
generated
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
namespace TweetDuck.Core.Other.Settings.Dialogs {
|
||||||
|
partial class DialogSettingsRestart {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||||||
|
this.btnRestart = new System.Windows.Forms.Button();
|
||||||
|
this.cbLogging = new System.Windows.Forms.CheckBox();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.cbDebugUpdates = new System.Windows.Forms.CheckBox();
|
||||||
|
this.labelLocale = new System.Windows.Forms.Label();
|
||||||
|
this.comboLocale = new System.Windows.Forms.ComboBox();
|
||||||
|
this.labelDataFolder = new System.Windows.Forms.Label();
|
||||||
|
this.tbDataFolder = new System.Windows.Forms.TextBox();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnCancel
|
||||||
|
//
|
||||||
|
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnCancel.Location = new System.Drawing.Point(160, 171);
|
||||||
|
this.btnCancel.Name = "btnCancel";
|
||||||
|
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnCancel.Size = new System.Drawing.Size(56, 23);
|
||||||
|
this.btnCancel.TabIndex = 7;
|
||||||
|
this.btnCancel.Text = "Cancel";
|
||||||
|
this.btnCancel.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||||
|
//
|
||||||
|
// btnRestart
|
||||||
|
//
|
||||||
|
this.btnRestart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnRestart.Location = new System.Drawing.Point(97, 171);
|
||||||
|
this.btnRestart.Name = "btnRestart";
|
||||||
|
this.btnRestart.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnRestart.Size = new System.Drawing.Size(57, 23);
|
||||||
|
this.btnRestart.TabIndex = 6;
|
||||||
|
this.btnRestart.Text = "Restart";
|
||||||
|
this.btnRestart.UseVisualStyleBackColor = true;
|
||||||
|
this.btnRestart.Click += new System.EventHandler(this.btnRestart_Click);
|
||||||
|
//
|
||||||
|
// cbLogging
|
||||||
|
//
|
||||||
|
this.cbLogging.AutoSize = true;
|
||||||
|
this.cbLogging.Location = new System.Drawing.Point(12, 12);
|
||||||
|
this.cbLogging.Name = "cbLogging";
|
||||||
|
this.cbLogging.Size = new System.Drawing.Size(64, 17);
|
||||||
|
this.cbLogging.TabIndex = 0;
|
||||||
|
this.cbLogging.Text = "Logging";
|
||||||
|
this.toolTip.SetToolTip(this.cbLogging, "Logging JavaScript output into a\r\ndebug.txt file in the data folder.");
|
||||||
|
this.cbLogging.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// cbDebugUpdates
|
||||||
|
//
|
||||||
|
this.cbDebugUpdates.AutoSize = true;
|
||||||
|
this.cbDebugUpdates.Location = new System.Drawing.Point(12, 35);
|
||||||
|
this.cbDebugUpdates.Name = "cbDebugUpdates";
|
||||||
|
this.cbDebugUpdates.Size = new System.Drawing.Size(127, 17);
|
||||||
|
this.cbDebugUpdates.TabIndex = 1;
|
||||||
|
this.cbDebugUpdates.Text = "Pre-Release Updates";
|
||||||
|
this.toolTip.SetToolTip(this.cbDebugUpdates, "Allows updating to pre-releases.");
|
||||||
|
this.cbDebugUpdates.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelLocale
|
||||||
|
//
|
||||||
|
this.labelLocale.AutoSize = true;
|
||||||
|
this.labelLocale.Location = new System.Drawing.Point(12, 67);
|
||||||
|
this.labelLocale.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelLocale.Name = "labelLocale";
|
||||||
|
this.labelLocale.Size = new System.Drawing.Size(39, 13);
|
||||||
|
this.labelLocale.TabIndex = 2;
|
||||||
|
this.labelLocale.Text = "Locale";
|
||||||
|
//
|
||||||
|
// comboLocale
|
||||||
|
//
|
||||||
|
this.comboLocale.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.comboLocale.FormattingEnabled = true;
|
||||||
|
this.comboLocale.Location = new System.Drawing.Point(15, 83);
|
||||||
|
this.comboLocale.Name = "comboLocale";
|
||||||
|
this.comboLocale.Size = new System.Drawing.Size(201, 21);
|
||||||
|
this.comboLocale.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// labelDataFolder
|
||||||
|
//
|
||||||
|
this.labelDataFolder.AutoSize = true;
|
||||||
|
this.labelDataFolder.Location = new System.Drawing.Point(12, 119);
|
||||||
|
this.labelDataFolder.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelDataFolder.Name = "labelDataFolder";
|
||||||
|
this.labelDataFolder.Size = new System.Drawing.Size(62, 13);
|
||||||
|
this.labelDataFolder.TabIndex = 4;
|
||||||
|
this.labelDataFolder.Text = "Data Folder";
|
||||||
|
//
|
||||||
|
// tbDataFolder
|
||||||
|
//
|
||||||
|
this.tbDataFolder.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tbDataFolder.Location = new System.Drawing.Point(15, 135);
|
||||||
|
this.tbDataFolder.Name = "tbDataFolder";
|
||||||
|
this.tbDataFolder.Size = new System.Drawing.Size(201, 20);
|
||||||
|
this.tbDataFolder.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// DialogSettingsRestart
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(228, 206);
|
||||||
|
this.Controls.Add(this.tbDataFolder);
|
||||||
|
this.Controls.Add(this.labelDataFolder);
|
||||||
|
this.Controls.Add(this.comboLocale);
|
||||||
|
this.Controls.Add(this.labelLocale);
|
||||||
|
this.Controls.Add(this.cbDebugUpdates);
|
||||||
|
this.Controls.Add(this.cbLogging);
|
||||||
|
this.Controls.Add(this.btnRestart);
|
||||||
|
this.Controls.Add(this.btnCancel);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "DialogSettingsRestart";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button btnCancel;
|
||||||
|
private System.Windows.Forms.Button btnRestart;
|
||||||
|
private System.Windows.Forms.CheckBox cbLogging;
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.CheckBox cbDebugUpdates;
|
||||||
|
private System.Windows.Forms.Label labelLocale;
|
||||||
|
private System.Windows.Forms.ComboBox comboLocale;
|
||||||
|
private System.Windows.Forms.Label labelDataFolder;
|
||||||
|
private System.Windows.Forms.TextBox tbDataFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Core/Other/Settings/Dialogs/DialogSettingsRestart.cs
Normal file
62
Core/Other/Settings/Dialogs/DialogSettingsRestart.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Configuration;
|
||||||
|
using TweetDuck.Data;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Settings.Dialogs{
|
||||||
|
sealed partial class DialogSettingsRestart : Form{
|
||||||
|
private const string DefaultLocale = "en-US";
|
||||||
|
|
||||||
|
public CommandLineArgs Args { get; private set; }
|
||||||
|
|
||||||
|
public DialogSettingsRestart(CommandLineArgs currentArgs){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
try{
|
||||||
|
object[] locales = Directory.EnumerateFiles(Path.Combine(Program.ProgramPath, "locales"), "*.pak", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToArray<object>();
|
||||||
|
comboLocale.Items.AddRange(locales);
|
||||||
|
}catch{
|
||||||
|
comboLocale.Items.Add(DefaultLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbLogging.Checked = currentArgs.HasFlag(Arguments.ArgLogging);
|
||||||
|
cbDebugUpdates.Checked = currentArgs.HasFlag(Arguments.ArgDebugUpdates);
|
||||||
|
comboLocale.SelectedItem = currentArgs.GetValue(Arguments.ArgLocale, DefaultLocale);
|
||||||
|
tbDataFolder.Text = currentArgs.GetValue(Arguments.ArgDataFolder, string.Empty);
|
||||||
|
|
||||||
|
Text = Program.BrandName+" Arguments";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnRestart_Click(object sender, EventArgs e){
|
||||||
|
Args = new CommandLineArgs();
|
||||||
|
|
||||||
|
if (cbLogging.Checked){
|
||||||
|
Args.AddFlag(Arguments.ArgLogging);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbDebugUpdates.Checked){
|
||||||
|
Args.AddFlag(Arguments.ArgDebugUpdates);
|
||||||
|
}
|
||||||
|
|
||||||
|
string locale = comboLocale.SelectedItem as string;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(locale) && locale != DefaultLocale){
|
||||||
|
Args.SetValue(Arguments.ArgLocale, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tbDataFolder.Text)){
|
||||||
|
Args.SetValue(Arguments.ArgDataFolder, tbDataFolder.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel_Click(object sender, EventArgs e){
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Core/Other/Settings/Export/ExportFileFlags.cs
Normal file
12
Core/Other/Settings/Export/ExportFileFlags.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Settings.Export{
|
||||||
|
[Flags]
|
||||||
|
enum ExportFileFlags{
|
||||||
|
None = 0,
|
||||||
|
Config = 1,
|
||||||
|
Session = 2,
|
||||||
|
PluginData = 4,
|
||||||
|
All = Config|Session|PluginData
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using TweetDuck.Configuration;
|
||||||
using TweetDck.Plugins;
|
using TweetDuck.Data;
|
||||||
|
using TweetDuck.Plugins;
|
||||||
|
using TweetDuck.Plugins.Enums;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings.Export{
|
namespace TweetDuck.Core.Other.Settings.Export{
|
||||||
sealed class ExportManager{
|
sealed class ExportManager{
|
||||||
private static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
|
private static readonly string CookiesPath = Path.Combine(Program.StoragePath, "Cookies");
|
||||||
private static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
|
private static readonly string TempCookiesPath = Path.Combine(Program.StoragePath, "CookiesTmp");
|
||||||
@@ -21,41 +23,28 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
this.plugins = plugins;
|
this.plugins = plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Export(bool includeSession){
|
public bool Export(ExportFileFlags flags){
|
||||||
try{
|
try{
|
||||||
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
|
||||||
stream.WriteFile("config", Program.ConfigFilePath);
|
if (flags.HasFlag(ExportFileFlags.Config)){
|
||||||
|
stream.WriteFile("config", Program.UserConfigFilePath);
|
||||||
foreach(PathInfo path in EnumerateFilesRelative(plugins.PathOfficialPlugins)){
|
|
||||||
string[] split = path.Relative.Split(CombinedFileStream.KeySeparator);
|
|
||||||
|
|
||||||
if (split.Length < 3){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (split.Length == 3){
|
|
||||||
if (split[2].Equals(".meta", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
split[2].Equals("browser.js", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
split[2].Equals("notification.js", StringComparison.OrdinalIgnoreCase)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
|
stream.WriteFile("plugin.config", Program.PluginConfigFilePath);
|
||||||
|
|
||||||
|
foreach(Plugin plugin in plugins.Plugins){
|
||||||
|
foreach(PathInfo path in EnumerateFilesRelative(plugin.GetPluginFolder(PluginFolder.Data))){
|
||||||
try{
|
try{
|
||||||
stream.WriteFile("plugin.off"+path.Relative, path.Full);
|
stream.WriteFile(new string[]{ "plugin.data", plugin.Identifier, path.Relative }, path.Full);
|
||||||
}catch(ArgumentOutOfRangeException e){
|
}catch(ArgumentOutOfRangeException e){
|
||||||
MessageBox.Show("Could not include a file in the export. "+e.Message, "Export Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
FormMessage.Warning("Export Profile", "Could not include a plugin file in the export. "+e.Message, FormMessage.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(PathInfo path in EnumerateFilesRelative(plugins.PathCustomPlugins)){
|
if (flags.HasFlag(ExportFileFlags.Session)){
|
||||||
try{
|
|
||||||
stream.WriteFile("plugin.usr"+path.Relative, path.Full);
|
|
||||||
}catch(ArgumentOutOfRangeException e){
|
|
||||||
MessageBox.Show("Could not include a file in the export. "+e.Message, "Export Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeSession){
|
|
||||||
stream.WriteFile("cookies", CookiesPath);
|
stream.WriteFile("cookies", CookiesPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +58,41 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Import(){
|
public ExportFileFlags GetImportFlags(){
|
||||||
|
ExportFileFlags flags = ExportFileFlags.None;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
bool updatedPlugins = false;
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
|
||||||
|
string key;
|
||||||
|
|
||||||
|
while((key = stream.SkipFile()) != null){
|
||||||
|
switch(key){
|
||||||
|
case "config":
|
||||||
|
flags |= ExportFileFlags.Config;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plugin.config":
|
||||||
|
case "plugin.data":
|
||||||
|
flags |= ExportFileFlags.PluginData;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "cookies":
|
||||||
|
flags |= ExportFileFlags.Session;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
LastException = e;
|
||||||
|
flags = ExportFileFlags.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Import(ExportFileFlags flags){
|
||||||
|
try{
|
||||||
|
HashSet<string> missingPlugins = new HashSet<string>();
|
||||||
|
|
||||||
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
|
using(CombinedFileStream stream = new CombinedFileStream(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None))){
|
||||||
CombinedFileStream.Entry entry;
|
CombinedFileStream.Entry entry;
|
||||||
@@ -79,32 +100,36 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
while((entry = stream.ReadFile()) != null){
|
while((entry = stream.ReadFile()) != null){
|
||||||
switch(entry.KeyName){
|
switch(entry.KeyName){
|
||||||
case "config":
|
case "config":
|
||||||
entry.WriteToFile(Program.ConfigFilePath);
|
if (flags.HasFlag(ExportFileFlags.Config)){
|
||||||
Program.ReloadConfig();
|
entry.WriteToFile(Program.UserConfigFilePath);
|
||||||
break;
|
|
||||||
|
|
||||||
case "plugin.off":
|
|
||||||
string root = Path.Combine(plugins.PathOfficialPlugins, entry.Identifier.Split(CombinedFileStream.KeySeparator)[1]);
|
|
||||||
|
|
||||||
if (Directory.Exists(root)){
|
|
||||||
entry.WriteToFile(Path.Combine(plugins.PathOfficialPlugins, entry.Identifier.Substring(entry.KeyName.Length+1)), true);
|
|
||||||
updatedPlugins = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "plugin.usr":
|
case "plugin.config":
|
||||||
entry.WriteToFile(Path.Combine(plugins.PathCustomPlugins, entry.Identifier.Substring(entry.KeyName.Length+1)), true);
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
updatedPlugins = true;
|
entry.WriteToFile(Program.PluginConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "plugin.data":
|
||||||
|
if (flags.HasFlag(ExportFileFlags.PluginData)){
|
||||||
|
string[] value = entry.KeyValue;
|
||||||
|
|
||||||
|
entry.WriteToFile(Path.Combine(Program.PluginDataPath, value[0], value[1]), true);
|
||||||
|
|
||||||
|
if (!plugins.IsPluginInstalled(value[0])){
|
||||||
|
missingPlugins.Add(value[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "cookies":
|
case "cookies":
|
||||||
if (MessageBox.Show("Do you want to import the login session? This will restart "+Program.BrandName+".", "Importing "+Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
if (flags.HasFlag(ExportFileFlags.Session)){
|
||||||
entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath));
|
entry.WriteToFile(Path.Combine(Program.StoragePath, TempCookiesPath));
|
||||||
|
|
||||||
// okay to and restart, 'cookies' is always the last entry
|
|
||||||
IsRestarting = true;
|
IsRestarting = true;
|
||||||
Program.Restart(new string[]{ "-importcookies" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -112,8 +137,15 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updatedPlugins){
|
if (missingPlugins.Count > 0){
|
||||||
plugins.Reload();
|
FormMessage.Information("Importing TweetDuck Profile", "Detected missing plugins when importing plugin data:\n"+string.Join("\n", missingPlugins), FormMessage.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsRestarting){
|
||||||
|
Program.Restart(Arguments.ArgImportCookies);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Program.ReloadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -138,10 +170,10 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<PathInfo> EnumerateFilesRelative(string root){
|
private static IEnumerable<PathInfo> EnumerateFilesRelative(string root){
|
||||||
return Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories).Select(fullPath => new PathInfo{
|
return Directory.Exists(root) ? Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories).Select(fullPath => new PathInfo{
|
||||||
Full = fullPath,
|
Full = fullPath,
|
||||||
Relative = fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, CombinedFileStream.KeySeparator) // includes leading separator character
|
Relative = fullPath.Substring(root.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) // strip leading separator character
|
||||||
});
|
}) : Enumerable.Empty<PathInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PathInfo{
|
private class PathInfo{
|
||||||
|
|||||||
335
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
335
Core/Other/Settings/TabSettingsAdvanced.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other.Settings {
|
namespace TweetDuck.Core.Other.Settings {
|
||||||
partial class TabSettingsAdvanced {
|
partial class TabSettingsAdvanced {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -29,193 +29,238 @@
|
|||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
this.btnEditCefArgs = new System.Windows.Forms.Button();
|
this.btnEditCefArgs = new System.Windows.Forms.Button();
|
||||||
this.btnEditCSS = new System.Windows.Forms.Button();
|
this.btnEditCSS = new System.Windows.Forms.Button();
|
||||||
this.btnRestartLog = new System.Windows.Forms.Button();
|
this.btnRestartArgs = new System.Windows.Forms.Button();
|
||||||
this.btnRestart = new System.Windows.Forms.Button();
|
this.btnRestart = new System.Windows.Forms.Button();
|
||||||
this.btnReset = new System.Windows.Forms.Button();
|
|
||||||
this.btnImport = new System.Windows.Forms.Button();
|
|
||||||
this.btnExport = new System.Windows.Forms.Button();
|
|
||||||
this.groupPerformance = new System.Windows.Forms.GroupBox();
|
|
||||||
this.groupConfiguration = new System.Windows.Forms.GroupBox();
|
|
||||||
this.groupApp = new System.Windows.Forms.GroupBox();
|
|
||||||
this.btnOpenAppFolder = new System.Windows.Forms.Button();
|
this.btnOpenAppFolder = new System.Windows.Forms.Button();
|
||||||
this.groupPerformance.SuspendLayout();
|
this.btnOpenDataFolder = new System.Windows.Forms.Button();
|
||||||
this.groupConfiguration.SuspendLayout();
|
this.numMemoryThreshold = new TweetDuck.Core.Controls.NumericUpDownEx();
|
||||||
this.groupApp.SuspendLayout();
|
this.checkBrowserGCReload = new System.Windows.Forms.CheckBox();
|
||||||
|
this.labelApp = new System.Windows.Forms.Label();
|
||||||
|
this.panelApp = new System.Windows.Forms.Panel();
|
||||||
|
this.labelPerformance = new System.Windows.Forms.Label();
|
||||||
|
this.panelPerformance = new System.Windows.Forms.Panel();
|
||||||
|
this.labelMemoryUsage = new System.Windows.Forms.Label();
|
||||||
|
this.panelConfiguration = new System.Windows.Forms.Panel();
|
||||||
|
this.labelConfiguration = new System.Windows.Forms.Label();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.numMemoryThreshold)).BeginInit();
|
||||||
|
this.panelApp.SuspendLayout();
|
||||||
|
this.panelPerformance.SuspendLayout();
|
||||||
|
this.panelConfiguration.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// btnClearCache
|
// btnClearCache
|
||||||
//
|
//
|
||||||
this.btnClearCache.Location = new System.Drawing.Point(6, 44);
|
this.btnClearCache.Location = new System.Drawing.Point(5, 28);
|
||||||
|
this.btnClearCache.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
this.btnClearCache.Name = "btnClearCache";
|
this.btnClearCache.Name = "btnClearCache";
|
||||||
this.btnClearCache.Size = new System.Drawing.Size(171, 23);
|
this.btnClearCache.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnClearCache.TabIndex = 14;
|
this.btnClearCache.TabIndex = 1;
|
||||||
this.btnClearCache.Text = "Clear Cache (calculating)";
|
this.btnClearCache.Text = "Clear Cache (calculating)";
|
||||||
this.toolTip.SetToolTip(this.btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources." +
|
this.toolTip.SetToolTip(this.btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
|
||||||
"");
|
|
||||||
this.btnClearCache.UseVisualStyleBackColor = true;
|
this.btnClearCache.UseVisualStyleBackColor = true;
|
||||||
this.btnClearCache.Click += new System.EventHandler(this.btnClearCache_Click);
|
|
||||||
//
|
//
|
||||||
// checkHardwareAcceleration
|
// checkHardwareAcceleration
|
||||||
//
|
//
|
||||||
this.checkHardwareAcceleration.AutoSize = true;
|
this.checkHardwareAcceleration.AutoSize = true;
|
||||||
this.checkHardwareAcceleration.Location = new System.Drawing.Point(6, 21);
|
this.checkHardwareAcceleration.Location = new System.Drawing.Point(6, 5);
|
||||||
this.checkHardwareAcceleration.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
this.checkHardwareAcceleration.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
this.checkHardwareAcceleration.Name = "checkHardwareAcceleration";
|
this.checkHardwareAcceleration.Name = "checkHardwareAcceleration";
|
||||||
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
|
this.checkHardwareAcceleration.Size = new System.Drawing.Size(134, 17);
|
||||||
this.checkHardwareAcceleration.TabIndex = 12;
|
this.checkHardwareAcceleration.TabIndex = 0;
|
||||||
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
|
this.checkHardwareAcceleration.Text = "Hardware Acceleration";
|
||||||
this.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses your graphics card to improve performance.\r\nDisable if you experience issues" +
|
this.toolTip.SetToolTip(this.checkHardwareAcceleration, "Uses graphics card to improve performance. Disable if you experience\r\nvisual glitches. This option will not be exported in a profile.");
|
||||||
" with rendering.");
|
|
||||||
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
|
this.checkHardwareAcceleration.UseVisualStyleBackColor = true;
|
||||||
this.checkHardwareAcceleration.CheckedChanged += new System.EventHandler(this.checkHardwareAcceleration_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// btnEditCefArgs
|
// btnEditCefArgs
|
||||||
//
|
//
|
||||||
this.btnEditCefArgs.Location = new System.Drawing.Point(6, 19);
|
this.btnEditCefArgs.Location = new System.Drawing.Point(5, 3);
|
||||||
|
this.btnEditCefArgs.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
this.btnEditCefArgs.Name = "btnEditCefArgs";
|
this.btnEditCefArgs.Name = "btnEditCefArgs";
|
||||||
this.btnEditCefArgs.Size = new System.Drawing.Size(171, 23);
|
this.btnEditCefArgs.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnEditCefArgs.TabIndex = 15;
|
this.btnEditCefArgs.TabIndex = 0;
|
||||||
this.btnEditCefArgs.Text = "Edit CEF Arguments";
|
this.btnEditCefArgs.Text = "Edit CEF Arguments";
|
||||||
this.toolTip.SetToolTip(this.btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
|
this.toolTip.SetToolTip(this.btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
|
||||||
this.btnEditCefArgs.UseVisualStyleBackColor = true;
|
this.btnEditCefArgs.UseVisualStyleBackColor = true;
|
||||||
this.btnEditCefArgs.Click += new System.EventHandler(this.btnEditCefArgs_Click);
|
|
||||||
//
|
//
|
||||||
// btnEditCSS
|
// btnEditCSS
|
||||||
//
|
//
|
||||||
this.btnEditCSS.Location = new System.Drawing.Point(6, 48);
|
this.btnEditCSS.Location = new System.Drawing.Point(155, 3);
|
||||||
this.btnEditCSS.Name = "btnEditCSS";
|
this.btnEditCSS.Name = "btnEditCSS";
|
||||||
this.btnEditCSS.Size = new System.Drawing.Size(171, 23);
|
this.btnEditCSS.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnEditCSS.TabIndex = 16;
|
this.btnEditCSS.TabIndex = 1;
|
||||||
this.btnEditCSS.Text = "Edit CSS";
|
this.btnEditCSS.Text = "Edit CSS";
|
||||||
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
|
this.toolTip.SetToolTip(this.btnEditCSS, "Set custom CSS for browser and notification windows.");
|
||||||
this.btnEditCSS.UseVisualStyleBackColor = true;
|
this.btnEditCSS.UseVisualStyleBackColor = true;
|
||||||
this.btnEditCSS.Click += new System.EventHandler(this.btnEditCSS_Click);
|
|
||||||
//
|
//
|
||||||
// btnRestartLog
|
// btnRestartArgs
|
||||||
//
|
//
|
||||||
this.btnRestartLog.Location = new System.Drawing.Point(6, 77);
|
this.btnRestartArgs.Location = new System.Drawing.Point(155, 32);
|
||||||
this.btnRestartLog.Name = "btnRestartLog";
|
this.btnRestartArgs.Name = "btnRestartArgs";
|
||||||
this.btnRestartLog.Size = new System.Drawing.Size(171, 23);
|
this.btnRestartArgs.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnRestartLog.TabIndex = 18;
|
this.btnRestartArgs.TabIndex = 3;
|
||||||
this.btnRestartLog.Text = "Restart with Logging";
|
this.btnRestartArgs.Text = "Restart with Arguments";
|
||||||
this.toolTip.SetToolTip(this.btnRestartLog, "Restarts the program and enables logging\r\ninto a debug.txt file in the installati" +
|
this.toolTip.SetToolTip(this.btnRestartArgs, "Restarts the program with customizable\r\ncommand line arguments.");
|
||||||
"on folder.");
|
this.btnRestartArgs.UseVisualStyleBackColor = true;
|
||||||
this.btnRestartLog.UseVisualStyleBackColor = true;
|
|
||||||
this.btnRestartLog.Click += new System.EventHandler(this.btnRestartLog_Click);
|
|
||||||
//
|
//
|
||||||
// btnRestart
|
// btnRestart
|
||||||
//
|
//
|
||||||
this.btnRestart.Location = new System.Drawing.Point(6, 48);
|
this.btnRestart.Location = new System.Drawing.Point(155, 3);
|
||||||
this.btnRestart.Name = "btnRestart";
|
this.btnRestart.Name = "btnRestart";
|
||||||
this.btnRestart.Size = new System.Drawing.Size(171, 23);
|
this.btnRestart.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnRestart.TabIndex = 17;
|
this.btnRestart.TabIndex = 2;
|
||||||
this.btnRestart.Text = "Restart the Program";
|
this.btnRestart.Text = "Restart the Program";
|
||||||
this.toolTip.SetToolTip(this.btnRestart, "Restarts the program using the same command\r\nline arguments that were used at lau" +
|
this.toolTip.SetToolTip(this.btnRestart, "Restarts the program using the same command\r\nline arguments that were used at launch.");
|
||||||
"nch.");
|
|
||||||
this.btnRestart.UseVisualStyleBackColor = true;
|
this.btnRestart.UseVisualStyleBackColor = true;
|
||||||
this.btnRestart.Click += new System.EventHandler(this.btnRestart_Click);
|
|
||||||
//
|
|
||||||
// btnReset
|
|
||||||
//
|
|
||||||
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
||||||
this.btnReset.AutoSize = true;
|
|
||||||
this.btnReset.Location = new System.Drawing.Point(190, 250);
|
|
||||||
this.btnReset.Name = "btnReset";
|
|
||||||
this.btnReset.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnReset.Size = new System.Drawing.Size(102, 23);
|
|
||||||
this.btnReset.TabIndex = 17;
|
|
||||||
this.btnReset.Text = "Restore Defaults";
|
|
||||||
this.btnReset.UseVisualStyleBackColor = true;
|
|
||||||
this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
|
|
||||||
//
|
|
||||||
// btnImport
|
|
||||||
//
|
|
||||||
this.btnImport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
||||||
this.btnImport.AutoSize = true;
|
|
||||||
this.btnImport.Location = new System.Drawing.Point(100, 250);
|
|
||||||
this.btnImport.Name = "btnImport";
|
|
||||||
this.btnImport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnImport.Size = new System.Drawing.Size(84, 23);
|
|
||||||
this.btnImport.TabIndex = 16;
|
|
||||||
this.btnImport.Text = "Import Profile";
|
|
||||||
this.btnImport.UseVisualStyleBackColor = true;
|
|
||||||
this.btnImport.Click += new System.EventHandler(this.btnImport_Click);
|
|
||||||
//
|
|
||||||
// btnExport
|
|
||||||
//
|
|
||||||
this.btnExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
|
||||||
this.btnExport.AutoSize = true;
|
|
||||||
this.btnExport.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
|
||||||
this.btnExport.Location = new System.Drawing.Point(9, 250);
|
|
||||||
this.btnExport.Name = "btnExport";
|
|
||||||
this.btnExport.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
|
||||||
this.btnExport.Size = new System.Drawing.Size(85, 23);
|
|
||||||
this.btnExport.TabIndex = 15;
|
|
||||||
this.btnExport.Text = "Export Profile";
|
|
||||||
this.btnExport.UseVisualStyleBackColor = true;
|
|
||||||
this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
|
|
||||||
//
|
|
||||||
// groupPerformance
|
|
||||||
//
|
|
||||||
this.groupPerformance.Controls.Add(this.checkHardwareAcceleration);
|
|
||||||
this.groupPerformance.Controls.Add(this.btnClearCache);
|
|
||||||
this.groupPerformance.Location = new System.Drawing.Point(9, 9);
|
|
||||||
this.groupPerformance.Name = "groupPerformance";
|
|
||||||
this.groupPerformance.Size = new System.Drawing.Size(183, 74);
|
|
||||||
this.groupPerformance.TabIndex = 18;
|
|
||||||
this.groupPerformance.TabStop = false;
|
|
||||||
this.groupPerformance.Text = "Performance";
|
|
||||||
//
|
|
||||||
// groupConfiguration
|
|
||||||
//
|
|
||||||
this.groupConfiguration.Controls.Add(this.btnEditCSS);
|
|
||||||
this.groupConfiguration.Controls.Add(this.btnEditCefArgs);
|
|
||||||
this.groupConfiguration.Location = new System.Drawing.Point(9, 89);
|
|
||||||
this.groupConfiguration.Name = "groupConfiguration";
|
|
||||||
this.groupConfiguration.Size = new System.Drawing.Size(183, 77);
|
|
||||||
this.groupConfiguration.TabIndex = 19;
|
|
||||||
this.groupConfiguration.TabStop = false;
|
|
||||||
this.groupConfiguration.Text = "Configuration";
|
|
||||||
//
|
|
||||||
// groupApp
|
|
||||||
//
|
|
||||||
this.groupApp.Controls.Add(this.btnOpenAppFolder);
|
|
||||||
this.groupApp.Controls.Add(this.btnRestartLog);
|
|
||||||
this.groupApp.Controls.Add(this.btnRestart);
|
|
||||||
this.groupApp.Location = new System.Drawing.Point(198, 9);
|
|
||||||
this.groupApp.Name = "groupApp";
|
|
||||||
this.groupApp.Size = new System.Drawing.Size(183, 106);
|
|
||||||
this.groupApp.TabIndex = 20;
|
|
||||||
this.groupApp.TabStop = false;
|
|
||||||
this.groupApp.Text = "App";
|
|
||||||
//
|
//
|
||||||
// btnOpenAppFolder
|
// btnOpenAppFolder
|
||||||
//
|
//
|
||||||
this.btnOpenAppFolder.Location = new System.Drawing.Point(6, 19);
|
this.btnOpenAppFolder.Location = new System.Drawing.Point(5, 3);
|
||||||
|
this.btnOpenAppFolder.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
this.btnOpenAppFolder.Name = "btnOpenAppFolder";
|
this.btnOpenAppFolder.Name = "btnOpenAppFolder";
|
||||||
this.btnOpenAppFolder.Size = new System.Drawing.Size(171, 23);
|
this.btnOpenAppFolder.Size = new System.Drawing.Size(144, 23);
|
||||||
this.btnOpenAppFolder.TabIndex = 16;
|
this.btnOpenAppFolder.TabIndex = 0;
|
||||||
this.btnOpenAppFolder.Text = "Open Program Folder";
|
this.btnOpenAppFolder.Text = "Open Program Folder";
|
||||||
this.toolTip.SetToolTip(this.btnOpenAppFolder, "Opens the folder where the app is located.");
|
this.toolTip.SetToolTip(this.btnOpenAppFolder, "Opens the folder where the app is located.");
|
||||||
this.btnOpenAppFolder.UseVisualStyleBackColor = true;
|
this.btnOpenAppFolder.UseVisualStyleBackColor = true;
|
||||||
this.btnOpenAppFolder.Click += new System.EventHandler(this.btnOpenAppFolder_Click);
|
//
|
||||||
|
// btnOpenDataFolder
|
||||||
|
//
|
||||||
|
this.btnOpenDataFolder.Location = new System.Drawing.Point(5, 32);
|
||||||
|
this.btnOpenDataFolder.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.btnOpenDataFolder.Name = "btnOpenDataFolder";
|
||||||
|
this.btnOpenDataFolder.Size = new System.Drawing.Size(144, 23);
|
||||||
|
this.btnOpenDataFolder.TabIndex = 1;
|
||||||
|
this.btnOpenDataFolder.Text = "Open Data Folder";
|
||||||
|
this.toolTip.SetToolTip(this.btnOpenDataFolder, "Opens the folder where your profile data is located.");
|
||||||
|
this.btnOpenDataFolder.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// numMemoryThreshold
|
||||||
|
//
|
||||||
|
this.numMemoryThreshold.Increment = new decimal(new int[] {
|
||||||
|
50,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.numMemoryThreshold.Location = new System.Drawing.Point(202, 82);
|
||||||
|
this.numMemoryThreshold.Maximum = 2000;
|
||||||
|
this.numMemoryThreshold.Minimum = 200;
|
||||||
|
this.numMemoryThreshold.Name = "numMemoryThreshold";
|
||||||
|
this.numMemoryThreshold.Size = new System.Drawing.Size(97, 20);
|
||||||
|
this.numMemoryThreshold.TabIndex = 4;
|
||||||
|
this.numMemoryThreshold.TextSuffix = " MB";
|
||||||
|
this.toolTip.SetToolTip(this.numMemoryThreshold, "Minimum amount of memory usage by the browser process to trigger the cleanup.\r\nThis is not a limit, the usage is allowed to exceed this value.");
|
||||||
|
this.numMemoryThreshold.Value = 400;
|
||||||
|
//
|
||||||
|
// checkBrowserGCReload
|
||||||
|
//
|
||||||
|
this.checkBrowserGCReload.AutoSize = true;
|
||||||
|
this.checkBrowserGCReload.Location = new System.Drawing.Point(6, 84);
|
||||||
|
this.checkBrowserGCReload.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkBrowserGCReload.Name = "checkBrowserGCReload";
|
||||||
|
this.checkBrowserGCReload.Size = new System.Drawing.Size(190, 17);
|
||||||
|
this.checkBrowserGCReload.TabIndex = 3;
|
||||||
|
this.checkBrowserGCReload.Text = "Enable Browser Memory Threshold";
|
||||||
|
this.toolTip.SetToolTip(this.checkBrowserGCReload, "Automatically reloads TweetDeck to save memory. This option only works if\r\nthe browser is in a \'default state\', i.e. all modals and drawers are closed, and\r\nall columns are scrolled to top. This option will not be exported in a profile.");
|
||||||
|
this.checkBrowserGCReload.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelApp
|
||||||
|
//
|
||||||
|
this.labelApp.AutoSize = true;
|
||||||
|
this.labelApp.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelApp.Location = new System.Drawing.Point(6, 8);
|
||||||
|
this.labelApp.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||||
|
this.labelApp.Name = "labelApp";
|
||||||
|
this.labelApp.Size = new System.Drawing.Size(38, 20);
|
||||||
|
this.labelApp.TabIndex = 0;
|
||||||
|
this.labelApp.Text = "App";
|
||||||
|
//
|
||||||
|
// panelApp
|
||||||
|
//
|
||||||
|
this.panelApp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelApp.Controls.Add(this.btnOpenDataFolder);
|
||||||
|
this.panelApp.Controls.Add(this.btnOpenAppFolder);
|
||||||
|
this.panelApp.Controls.Add(this.btnRestart);
|
||||||
|
this.panelApp.Controls.Add(this.btnRestartArgs);
|
||||||
|
this.panelApp.Location = new System.Drawing.Point(9, 31);
|
||||||
|
this.panelApp.Name = "panelApp";
|
||||||
|
this.panelApp.Size = new System.Drawing.Size(322, 59);
|
||||||
|
this.panelApp.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// labelPerformance
|
||||||
|
//
|
||||||
|
this.labelPerformance.AutoSize = true;
|
||||||
|
this.labelPerformance.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelPerformance.Location = new System.Drawing.Point(6, 114);
|
||||||
|
this.labelPerformance.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelPerformance.Name = "labelPerformance";
|
||||||
|
this.labelPerformance.Size = new System.Drawing.Size(100, 20);
|
||||||
|
this.labelPerformance.TabIndex = 2;
|
||||||
|
this.labelPerformance.Text = "Performance";
|
||||||
|
//
|
||||||
|
// panelPerformance
|
||||||
|
//
|
||||||
|
this.panelPerformance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelPerformance.Controls.Add(this.checkBrowserGCReload);
|
||||||
|
this.panelPerformance.Controls.Add(this.numMemoryThreshold);
|
||||||
|
this.panelPerformance.Controls.Add(this.labelMemoryUsage);
|
||||||
|
this.panelPerformance.Controls.Add(this.checkHardwareAcceleration);
|
||||||
|
this.panelPerformance.Controls.Add(this.btnClearCache);
|
||||||
|
this.panelPerformance.Location = new System.Drawing.Point(9, 137);
|
||||||
|
this.panelPerformance.Name = "panelPerformance";
|
||||||
|
this.panelPerformance.Size = new System.Drawing.Size(322, 105);
|
||||||
|
this.panelPerformance.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// labelMemoryUsage
|
||||||
|
//
|
||||||
|
this.labelMemoryUsage.AutoSize = true;
|
||||||
|
this.labelMemoryUsage.Location = new System.Drawing.Point(3, 66);
|
||||||
|
this.labelMemoryUsage.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelMemoryUsage.Name = "labelMemoryUsage";
|
||||||
|
this.labelMemoryUsage.Size = new System.Drawing.Size(78, 13);
|
||||||
|
this.labelMemoryUsage.TabIndex = 2;
|
||||||
|
this.labelMemoryUsage.Text = "Memory Usage";
|
||||||
|
//
|
||||||
|
// panelConfiguration
|
||||||
|
//
|
||||||
|
this.panelConfiguration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelConfiguration.Controls.Add(this.btnEditCSS);
|
||||||
|
this.panelConfiguration.Controls.Add(this.btnEditCefArgs);
|
||||||
|
this.panelConfiguration.Location = new System.Drawing.Point(9, 289);
|
||||||
|
this.panelConfiguration.Name = "panelConfiguration";
|
||||||
|
this.panelConfiguration.Size = new System.Drawing.Size(322, 29);
|
||||||
|
this.panelConfiguration.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// labelConfiguration
|
||||||
|
//
|
||||||
|
this.labelConfiguration.AutoSize = true;
|
||||||
|
this.labelConfiguration.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelConfiguration.Location = new System.Drawing.Point(6, 266);
|
||||||
|
this.labelConfiguration.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelConfiguration.Name = "labelConfiguration";
|
||||||
|
this.labelConfiguration.Size = new System.Drawing.Size(104, 20);
|
||||||
|
this.labelConfiguration.TabIndex = 4;
|
||||||
|
this.labelConfiguration.Text = "Configuration";
|
||||||
//
|
//
|
||||||
// TabSettingsAdvanced
|
// TabSettingsAdvanced
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.Controls.Add(this.groupApp);
|
this.Controls.Add(this.labelConfiguration);
|
||||||
this.Controls.Add(this.groupConfiguration);
|
this.Controls.Add(this.panelConfiguration);
|
||||||
this.Controls.Add(this.groupPerformance);
|
this.Controls.Add(this.panelPerformance);
|
||||||
this.Controls.Add(this.btnReset);
|
this.Controls.Add(this.labelPerformance);
|
||||||
this.Controls.Add(this.btnImport);
|
this.Controls.Add(this.panelApp);
|
||||||
this.Controls.Add(this.btnExport);
|
this.Controls.Add(this.labelApp);
|
||||||
this.Name = "TabSettingsAdvanced";
|
this.Name = "TabSettingsAdvanced";
|
||||||
this.Size = new System.Drawing.Size(478, 282);
|
this.Size = new System.Drawing.Size(340, 328);
|
||||||
this.groupPerformance.ResumeLayout(false);
|
((System.ComponentModel.ISupportInitialize)(this.numMemoryThreshold)).EndInit();
|
||||||
this.groupPerformance.PerformLayout();
|
this.panelApp.ResumeLayout(false);
|
||||||
this.groupConfiguration.ResumeLayout(false);
|
this.panelPerformance.ResumeLayout(false);
|
||||||
this.groupApp.ResumeLayout(false);
|
this.panelPerformance.PerformLayout();
|
||||||
|
this.panelConfiguration.ResumeLayout(false);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
@@ -226,16 +271,20 @@
|
|||||||
private System.Windows.Forms.Button btnClearCache;
|
private System.Windows.Forms.Button btnClearCache;
|
||||||
private System.Windows.Forms.CheckBox checkHardwareAcceleration;
|
private System.Windows.Forms.CheckBox checkHardwareAcceleration;
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
private System.Windows.Forms.Button btnReset;
|
|
||||||
private System.Windows.Forms.Button btnImport;
|
|
||||||
private System.Windows.Forms.Button btnExport;
|
|
||||||
private System.Windows.Forms.GroupBox groupPerformance;
|
|
||||||
private System.Windows.Forms.GroupBox groupConfiguration;
|
|
||||||
private System.Windows.Forms.Button btnEditCefArgs;
|
private System.Windows.Forms.Button btnEditCefArgs;
|
||||||
private System.Windows.Forms.Button btnEditCSS;
|
private System.Windows.Forms.Button btnEditCSS;
|
||||||
private System.Windows.Forms.GroupBox groupApp;
|
private System.Windows.Forms.Button btnRestartArgs;
|
||||||
private System.Windows.Forms.Button btnRestartLog;
|
|
||||||
private System.Windows.Forms.Button btnRestart;
|
private System.Windows.Forms.Button btnRestart;
|
||||||
private System.Windows.Forms.Button btnOpenAppFolder;
|
private System.Windows.Forms.Button btnOpenAppFolder;
|
||||||
|
private System.Windows.Forms.Button btnOpenDataFolder;
|
||||||
|
private System.Windows.Forms.Label labelApp;
|
||||||
|
private System.Windows.Forms.Panel panelApp;
|
||||||
|
private System.Windows.Forms.Label labelPerformance;
|
||||||
|
private System.Windows.Forms.Panel panelPerformance;
|
||||||
|
private System.Windows.Forms.Panel panelConfiguration;
|
||||||
|
private System.Windows.Forms.Label labelConfiguration;
|
||||||
|
private System.Windows.Forms.Label labelMemoryUsage;
|
||||||
|
private Controls.NumericUpDownEx numMemoryThreshold;
|
||||||
|
private System.Windows.Forms.CheckBox checkBrowserGCReload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Configuration;
|
||||||
using TweetDck.Core.Other.Settings.Dialogs;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Core.Other.Settings.Export;
|
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||||
using TweetDck.Core.Utils;
|
using TweetDuck.Core.Utils;
|
||||||
using TweetDck.Plugins;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
partial class TabSettingsAdvanced : BaseTabSettings{
|
partial class TabSettingsAdvanced : BaseTabSettings{
|
||||||
private readonly Action browserReloadAction;
|
private static SystemConfig SysConfig => Program.SystemConfig;
|
||||||
private readonly PluginManager plugins;
|
|
||||||
|
|
||||||
public TabSettingsAdvanced(Action browserReloadAction, PluginManager plugins){
|
private readonly Action<string> reinjectBrowserCSS;
|
||||||
|
|
||||||
|
public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.browserReloadAction = browserReloadAction;
|
this.reinjectBrowserCSS = reinjectBrowserCSS;
|
||||||
this.plugins = plugins;
|
|
||||||
|
|
||||||
checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
|
if (SystemConfig.IsHardwareAccelerationSupported){
|
||||||
|
checkHardwareAcceleration.Checked = SysConfig.HardwareAcceleration;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
checkHardwareAcceleration.Enabled = false;
|
||||||
|
checkHardwareAcceleration.Checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBrowserGCReload.Checked = SysConfig.EnableBrowserGCReload;
|
||||||
|
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
||||||
|
numMemoryThreshold.SetValueSafe(SysConfig.BrowserMemoryThreshold);
|
||||||
|
|
||||||
BrowserCache.CalculateCacheSize(bytes => this.InvokeSafe(() => {
|
BrowserCache.CalculateCacheSize(bytes => this.InvokeSafe(() => {
|
||||||
if (bytes == -1L){
|
if (bytes == -1L){
|
||||||
@@ -30,143 +39,115 @@ namespace TweetDck.Core.Other.Settings{
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnClearCache_Click(object sender, EventArgs e){
|
public override void OnReady(){
|
||||||
if (!Ready)return;
|
btnClearCache.Click += btnClearCache_Click;
|
||||||
|
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
|
||||||
|
|
||||||
|
checkBrowserGCReload.CheckedChanged += checkBrowserGCReload_CheckedChanged;
|
||||||
|
numMemoryThreshold.ValueChanged += numMemoryThreshold_ValueChanged;
|
||||||
|
|
||||||
|
btnEditCefArgs.Click += btnEditCefArgs_Click;
|
||||||
|
btnEditCSS.Click += btnEditCSS_Click;
|
||||||
|
|
||||||
|
btnOpenAppFolder.Click += btnOpenAppFolder_Click;
|
||||||
|
btnOpenDataFolder.Click += btnOpenDataFolder_Click;
|
||||||
|
btnRestart.Click += btnRestart_Click;
|
||||||
|
btnRestartArgs.Click += btnRestartArgs_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
SysConfig.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnClearCache_Click(object sender, EventArgs e){
|
||||||
btnClearCache.Enabled = false;
|
btnClearCache.Enabled = false;
|
||||||
BrowserCache.SetClearOnExit();
|
BrowserCache.SetClearOnExit();
|
||||||
|
FormMessage.Information("Clear Cache", "Cache will be automatically cleared when TweetDuck exits.", FormMessage.OK);
|
||||||
MessageBox.Show("Cache will be automatically cleared when "+Program.BrandName+" exits.", "Clear Cache", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
|
private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
SysConfig.HardwareAcceleration = checkHardwareAcceleration.Checked;
|
||||||
|
PromptRestart(); // calls OnClosing
|
||||||
bool succeeded = false;
|
|
||||||
|
|
||||||
if (checkHardwareAcceleration.Checked){
|
|
||||||
if (HardwareAcceleration.CanEnable){
|
|
||||||
succeeded = HardwareAcceleration.Enable();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
MessageBox.Show("Cannot enable hardware acceleration, the libraries libEGL.dll and libGLESv2.dll could not be restored.", Program.BrandName+" Settings", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
succeeded = HardwareAcceleration.Disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (succeeded){
|
private void checkBrowserGCReload_CheckedChanged(object sender, EventArgs e){
|
||||||
PromptRestart();
|
SysConfig.EnableBrowserGCReload = checkBrowserGCReload.Checked;
|
||||||
}
|
numMemoryThreshold.Enabled = checkBrowserGCReload.Checked;
|
||||||
else{
|
|
||||||
checkHardwareAcceleration.CheckedChanged -= checkHardwareAcceleration_CheckedChanged;
|
|
||||||
checkHardwareAcceleration.Checked = HardwareAcceleration.IsEnabled;
|
|
||||||
checkHardwareAcceleration.CheckedChanged += checkHardwareAcceleration_CheckedChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void numMemoryThreshold_ValueChanged(object sender, EventArgs e){
|
||||||
|
SysConfig.BrowserMemoryThreshold = (int)numMemoryThreshold.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnEditCefArgs_Click(object sender, EventArgs e){
|
private void btnEditCefArgs_Click(object sender, EventArgs e){
|
||||||
DialogSettingsCefArgs form = new DialogSettingsCefArgs();
|
DialogSettingsCefArgs form = new DialogSettingsCefArgs();
|
||||||
|
|
||||||
if (form.ShowDialog(ParentForm) == DialogResult.OK){
|
form.VisibleChanged += (sender2, args2) => {
|
||||||
|
form.MoveToCenter(ParentForm);
|
||||||
|
};
|
||||||
|
|
||||||
|
form.FormClosed += (sender2, args2) => {
|
||||||
|
RestoreParentForm();
|
||||||
|
|
||||||
|
if (form.DialogResult == DialogResult.OK){
|
||||||
Config.CustomCefArgs = form.CefArgs;
|
Config.CustomCefArgs = form.CefArgs;
|
||||||
form.Dispose();
|
|
||||||
PromptRestart();
|
PromptRestart();
|
||||||
}
|
|
||||||
else{
|
|
||||||
form.Dispose();
|
form.Dispose();
|
||||||
}
|
}
|
||||||
|
else form.Dispose();
|
||||||
|
};
|
||||||
|
|
||||||
|
form.Show(ParentForm);
|
||||||
|
NativeMethods.SetFormDisabled(ParentForm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnEditCSS_Click(object sender, EventArgs e){
|
private void btnEditCSS_Click(object sender, EventArgs e){
|
||||||
using(DialogSettingsCSS form = new DialogSettingsCSS()){
|
DialogSettingsCSS form = new DialogSettingsCSS(reinjectBrowserCSS);
|
||||||
if (form.ShowDialog(ParentForm) == DialogResult.OK){
|
|
||||||
bool hasChangedBrowser = form.BrowserCSS != Config.CustomBrowserCSS;
|
|
||||||
|
|
||||||
|
form.VisibleChanged += (sender2, args2) => {
|
||||||
|
form.MoveToCenter(ParentForm);
|
||||||
|
};
|
||||||
|
|
||||||
|
form.FormClosed += (sender2, args2) => {
|
||||||
|
RestoreParentForm();
|
||||||
|
|
||||||
|
if (form.DialogResult == DialogResult.OK){
|
||||||
Config.CustomBrowserCSS = form.BrowserCSS;
|
Config.CustomBrowserCSS = form.BrowserCSS;
|
||||||
Config.CustomNotificationCSS = form.NotificationCSS;
|
Config.CustomNotificationCSS = form.NotificationCSS;
|
||||||
|
|
||||||
if (hasChangedBrowser && MessageBox.Show("The browser CSS has changed, do you want to reload it?", "Browser CSS Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
|
||||||
browserReloadAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnExport_Click(object sender, EventArgs e){
|
reinjectBrowserCSS(Config.CustomBrowserCSS); // reinject on cancel too, because the CSS is updated while typing
|
||||||
DialogResult resultSaveCredentials = MessageBox.Show("Do you want to include your login session? This will not save your password into the file, but it will allow anyone with the file to login into TweetDeck as you.", "Export "+Program.BrandName+" Settings", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3);
|
form.Dispose();
|
||||||
if (resultSaveCredentials == DialogResult.Cancel)return;
|
};
|
||||||
|
|
||||||
bool saveCredentials = resultSaveCredentials == DialogResult.Yes;
|
form.Show(ParentForm);
|
||||||
string file;
|
NativeMethods.SetFormDisabled(ParentForm, true);
|
||||||
|
|
||||||
using(SaveFileDialog dialog = new SaveFileDialog{
|
|
||||||
AddExtension = true,
|
|
||||||
AutoUpgradeEnabled = true,
|
|
||||||
OverwritePrompt = true,
|
|
||||||
DefaultExt = "tdsettings",
|
|
||||||
FileName = Program.BrandName+".tdsettings",
|
|
||||||
Title = "Export "+Program.BrandName+" Settings",
|
|
||||||
Filter = Program.BrandName+" Settings (*.tdsettings)|*.tdsettings"
|
|
||||||
}){
|
|
||||||
file = dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file != null){
|
|
||||||
Program.UserConfig.Save();
|
|
||||||
|
|
||||||
ExportManager manager = new ExportManager(file, plugins);
|
|
||||||
|
|
||||||
if (!manager.Export(saveCredentials)){
|
|
||||||
Program.Reporter.HandleException("Profile Export Error", "An exception happened while exporting "+Program.BrandName+" settings.", true, manager.LastException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnImport_Click(object sender, EventArgs e){
|
|
||||||
string file;
|
|
||||||
|
|
||||||
using(OpenFileDialog dialog = new OpenFileDialog{
|
|
||||||
AutoUpgradeEnabled = true,
|
|
||||||
DereferenceLinks = true,
|
|
||||||
Title = "Import "+Program.BrandName+" Settings",
|
|
||||||
Filter = Program.BrandName+" Settings (*.tdsettings)|*.tdsettings"
|
|
||||||
}){
|
|
||||||
file = dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file != null){
|
|
||||||
ExportManager manager = new ExportManager(file, plugins);
|
|
||||||
|
|
||||||
if (manager.Import()){
|
|
||||||
if (!manager.IsRestarting){
|
|
||||||
((FormSettings)ParentForm).ReloadUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Program.Reporter.HandleException("Profile Import Error", "An exception happened while importing "+Program.BrandName+" settings.", true, manager.LastException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnReset_Click(object sender, EventArgs e){
|
|
||||||
if (MessageBox.Show("This will reset all of your settings, including disabled plugins. Do you want to proceed?", "Reset "+Program.BrandName+" Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes){
|
|
||||||
Program.ResetConfig();
|
|
||||||
((FormSettings)ParentForm).ReloadUI();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnOpenAppFolder_Click(object sender, EventArgs e){
|
private void btnOpenAppFolder_Click(object sender, EventArgs e){
|
||||||
using(Process.Start("explorer.exe", "\""+Program.ProgramPath+"\"")){}
|
using(Process.Start("explorer.exe", "\""+Program.ProgramPath+"\"")){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void btnOpenDataFolder_Click(object sender, EventArgs e){
|
||||||
|
using(Process.Start("explorer.exe", "\""+Program.StoragePath+"\"")){}
|
||||||
|
}
|
||||||
|
|
||||||
private void btnRestart_Click(object sender, EventArgs e){
|
private void btnRestart_Click(object sender, EventArgs e){
|
||||||
Program.Restart();
|
Program.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnRestartLog_Click(object sender, EventArgs e){
|
private void btnRestartArgs_Click(object sender, EventArgs e){
|
||||||
Program.Restart(new string[]{ "-log" });
|
using(DialogSettingsRestart dialog = new DialogSettingsRestart(Arguments.GetCurrentClean())){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
Program.RestartWithArgs(dialog.Args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RestoreParentForm(){
|
||||||
|
if (ParentForm != null){ // when the parent is closed first, ParentForm is null in FormClosed event
|
||||||
|
NativeMethods.SetFormDisabled(ParentForm, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
276
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
276
Core/Other/Settings/TabSettingsGeneral.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other.Settings {
|
namespace TweetDuck.Core.Other.Settings {
|
||||||
partial class TabSettingsGeneral {
|
partial class TabSettingsGeneral {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -29,110 +29,266 @@
|
|||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
this.checkTrayHighlight = new System.Windows.Forms.CheckBox();
|
this.checkTrayHighlight = new System.Windows.Forms.CheckBox();
|
||||||
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
|
this.checkSpellCheck = new System.Windows.Forms.CheckBox();
|
||||||
this.groupTray = new System.Windows.Forms.GroupBox();
|
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
|
||||||
|
this.btnCheckUpdates = new System.Windows.Forms.Button();
|
||||||
|
this.labelZoomValue = new System.Windows.Forms.Label();
|
||||||
|
this.checkSwitchAccountSelectors = new System.Windows.Forms.CheckBox();
|
||||||
this.labelTrayIcon = new System.Windows.Forms.Label();
|
this.labelTrayIcon = new System.Windows.Forms.Label();
|
||||||
this.groupInterface = new System.Windows.Forms.GroupBox();
|
this.trackBarZoom = new System.Windows.Forms.TrackBar();
|
||||||
this.groupTray.SuspendLayout();
|
this.labelZoom = new System.Windows.Forms.Label();
|
||||||
this.groupInterface.SuspendLayout();
|
this.zoomUpdateTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.labelUI = new System.Windows.Forms.Label();
|
||||||
|
this.panelUI = new System.Windows.Forms.Panel();
|
||||||
|
this.labelTray = new System.Windows.Forms.Label();
|
||||||
|
this.panelUpdates = new System.Windows.Forms.Panel();
|
||||||
|
this.panelTray = new System.Windows.Forms.Panel();
|
||||||
|
this.labelUpdates = new System.Windows.Forms.Label();
|
||||||
|
this.checkBestImageQuality = new System.Windows.Forms.CheckBox();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).BeginInit();
|
||||||
|
this.panelUI.SuspendLayout();
|
||||||
|
this.panelUpdates.SuspendLayout();
|
||||||
|
this.panelTray.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// checkExpandLinks
|
// checkExpandLinks
|
||||||
//
|
//
|
||||||
this.checkExpandLinks.AutoSize = true;
|
this.checkExpandLinks.AutoSize = true;
|
||||||
this.checkExpandLinks.Location = new System.Drawing.Point(9, 21);
|
this.checkExpandLinks.Location = new System.Drawing.Point(6, 5);
|
||||||
this.checkExpandLinks.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
this.checkExpandLinks.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
this.checkExpandLinks.Name = "checkExpandLinks";
|
this.checkExpandLinks.Name = "checkExpandLinks";
|
||||||
this.checkExpandLinks.Size = new System.Drawing.Size(166, 17);
|
this.checkExpandLinks.Size = new System.Drawing.Size(166, 17);
|
||||||
this.checkExpandLinks.TabIndex = 14;
|
this.checkExpandLinks.TabIndex = 0;
|
||||||
this.checkExpandLinks.Text = "Expand Links When Hovered";
|
this.checkExpandLinks.Text = "Expand Links When Hovered";
|
||||||
this.toolTip.SetToolTip(this.checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a toolti" +
|
this.toolTip.SetToolTip(this.checkExpandLinks, "Expands links inside the tweets. If disabled,\r\nthe full links show up in a tooltip instead.");
|
||||||
"p instead.");
|
|
||||||
this.checkExpandLinks.UseVisualStyleBackColor = true;
|
this.checkExpandLinks.UseVisualStyleBackColor = true;
|
||||||
this.checkExpandLinks.CheckedChanged += new System.EventHandler(this.checkExpandLinks_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// comboBoxTrayType
|
// comboBoxTrayType
|
||||||
//
|
//
|
||||||
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.comboBoxTrayType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
this.comboBoxTrayType.FormattingEnabled = true;
|
this.comboBoxTrayType.FormattingEnabled = true;
|
||||||
this.comboBoxTrayType.Location = new System.Drawing.Point(6, 19);
|
this.comboBoxTrayType.Location = new System.Drawing.Point(5, 5);
|
||||||
|
this.comboBoxTrayType.Margin = new System.Windows.Forms.Padding(5, 5, 3, 3);
|
||||||
this.comboBoxTrayType.Name = "comboBoxTrayType";
|
this.comboBoxTrayType.Name = "comboBoxTrayType";
|
||||||
this.comboBoxTrayType.Size = new System.Drawing.Size(171, 21);
|
this.comboBoxTrayType.Size = new System.Drawing.Size(144, 21);
|
||||||
this.comboBoxTrayType.TabIndex = 13;
|
this.comboBoxTrayType.TabIndex = 0;
|
||||||
this.toolTip.SetToolTip(this.comboBoxTrayType, "Changes behavior of the Tray icon.\r\nRight-click the icon for an action menu.");
|
this.toolTip.SetToolTip(this.comboBoxTrayType, "Changes behavior of the Tray icon.\r\nRight-click the icon for an action menu.");
|
||||||
this.comboBoxTrayType.SelectedIndexChanged += new System.EventHandler(this.comboBoxTrayType_SelectedIndexChanged);
|
|
||||||
//
|
//
|
||||||
// checkTrayHighlight
|
// checkTrayHighlight
|
||||||
//
|
//
|
||||||
this.checkTrayHighlight.AutoSize = true;
|
this.checkTrayHighlight.AutoSize = true;
|
||||||
this.checkTrayHighlight.Location = new System.Drawing.Point(9, 70);
|
this.checkTrayHighlight.Location = new System.Drawing.Point(6, 56);
|
||||||
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
this.checkTrayHighlight.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
this.checkTrayHighlight.Name = "checkTrayHighlight";
|
this.checkTrayHighlight.Name = "checkTrayHighlight";
|
||||||
this.checkTrayHighlight.Size = new System.Drawing.Size(103, 17);
|
this.checkTrayHighlight.Size = new System.Drawing.Size(103, 17);
|
||||||
this.checkTrayHighlight.TabIndex = 15;
|
this.checkTrayHighlight.TabIndex = 2;
|
||||||
this.checkTrayHighlight.Text = "Enable Highlight";
|
this.checkTrayHighlight.Text = "Enable Highlight";
|
||||||
this.toolTip.SetToolTip(this.checkTrayHighlight, "Highlights the tray icon if there are new tweets.\r\nOnly works for columns with po" +
|
this.toolTip.SetToolTip(this.checkTrayHighlight, "Highlights the tray icon if there are new tweets.\r\nOnly works for columns with popup or audio notifications.\r\nThe icon resets when the main window is restored.");
|
||||||
"pup or audio notifications.\r\nThe icon resets when the main window is restored.");
|
|
||||||
this.checkTrayHighlight.UseVisualStyleBackColor = true;
|
this.checkTrayHighlight.UseVisualStyleBackColor = true;
|
||||||
this.checkTrayHighlight.CheckedChanged += new System.EventHandler(this.checkTrayHighlight_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// checkSpellCheck
|
// checkSpellCheck
|
||||||
//
|
//
|
||||||
this.checkSpellCheck.AutoSize = true;
|
this.checkSpellCheck.AutoSize = true;
|
||||||
this.checkSpellCheck.Location = new System.Drawing.Point(9, 44);
|
this.checkSpellCheck.Location = new System.Drawing.Point(6, 74);
|
||||||
|
this.checkSpellCheck.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
this.checkSpellCheck.Name = "checkSpellCheck";
|
this.checkSpellCheck.Name = "checkSpellCheck";
|
||||||
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
|
this.checkSpellCheck.Size = new System.Drawing.Size(119, 17);
|
||||||
this.checkSpellCheck.TabIndex = 15;
|
this.checkSpellCheck.TabIndex = 3;
|
||||||
this.checkSpellCheck.Text = "Enable Spell Check";
|
this.checkSpellCheck.Text = "Enable Spell Check";
|
||||||
this.toolTip.SetToolTip(this.checkSpellCheck, "Underlines words that are spelled incorrectly.");
|
this.toolTip.SetToolTip(this.checkSpellCheck, "Underlines words that are spelled incorrectly.");
|
||||||
this.checkSpellCheck.UseVisualStyleBackColor = true;
|
this.checkSpellCheck.UseVisualStyleBackColor = true;
|
||||||
this.checkSpellCheck.CheckedChanged += new System.EventHandler(this.checkSpellCheck_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// groupTray
|
// checkUpdateNotifications
|
||||||
//
|
//
|
||||||
this.groupTray.Controls.Add(this.checkTrayHighlight);
|
this.checkUpdateNotifications.AutoSize = true;
|
||||||
this.groupTray.Controls.Add(this.labelTrayIcon);
|
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 5);
|
||||||
this.groupTray.Controls.Add(this.comboBoxTrayType);
|
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
this.groupTray.Location = new System.Drawing.Point(9, 86);
|
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
||||||
this.groupTray.Name = "groupTray";
|
this.checkUpdateNotifications.Size = new System.Drawing.Size(165, 17);
|
||||||
this.groupTray.Size = new System.Drawing.Size(183, 93);
|
this.checkUpdateNotifications.TabIndex = 0;
|
||||||
this.groupTray.TabIndex = 15;
|
this.checkUpdateNotifications.Text = "Check Updates Automatically";
|
||||||
this.groupTray.TabStop = false;
|
this.toolTip.SetToolTip(this.checkUpdateNotifications, "Checks for updates every hour.\r\nIf an update is dismissed, it will not appear again.");
|
||||||
this.groupTray.Text = "System Tray";
|
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnCheckUpdates
|
||||||
|
//
|
||||||
|
this.btnCheckUpdates.Location = new System.Drawing.Point(5, 28);
|
||||||
|
this.btnCheckUpdates.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.btnCheckUpdates.Name = "btnCheckUpdates";
|
||||||
|
this.btnCheckUpdates.Size = new System.Drawing.Size(144, 23);
|
||||||
|
this.btnCheckUpdates.TabIndex = 1;
|
||||||
|
this.btnCheckUpdates.Text = "Check Updates Now";
|
||||||
|
this.toolTip.SetToolTip(this.btnCheckUpdates, "Forces an update check, even for updates that had been dismissed.");
|
||||||
|
this.btnCheckUpdates.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelZoomValue
|
||||||
|
//
|
||||||
|
this.labelZoomValue.BackColor = System.Drawing.Color.Transparent;
|
||||||
|
this.labelZoomValue.Location = new System.Drawing.Point(141, 123);
|
||||||
|
this.labelZoomValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelZoomValue.Name = "labelZoomValue";
|
||||||
|
this.labelZoomValue.Size = new System.Drawing.Size(38, 13);
|
||||||
|
this.labelZoomValue.TabIndex = 6;
|
||||||
|
this.labelZoomValue.Text = "100%";
|
||||||
|
this.labelZoomValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
this.toolTip.SetToolTip(this.labelZoomValue, "Changes the zoom level.\r\nAlso affects notifications and screenshots.");
|
||||||
|
//
|
||||||
|
// checkSwitchAccountSelectors
|
||||||
|
//
|
||||||
|
this.checkSwitchAccountSelectors.AutoSize = true;
|
||||||
|
this.checkSwitchAccountSelectors.Location = new System.Drawing.Point(6, 28);
|
||||||
|
this.checkSwitchAccountSelectors.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkSwitchAccountSelectors.Name = "checkSwitchAccountSelectors";
|
||||||
|
this.checkSwitchAccountSelectors.Size = new System.Drawing.Size(172, 17);
|
||||||
|
this.checkSwitchAccountSelectors.TabIndex = 1;
|
||||||
|
this.checkSwitchAccountSelectors.Text = "Shift Selects Multiple Accounts";
|
||||||
|
this.toolTip.SetToolTip(this.checkSwitchAccountSelectors, "When (re)tweeting, click to select a single account or hold Shift to\r\nselect multiple accounts, instead of TweetDeck\'s default behavior.");
|
||||||
|
this.checkSwitchAccountSelectors.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// labelTrayIcon
|
// labelTrayIcon
|
||||||
//
|
//
|
||||||
this.labelTrayIcon.AutoSize = true;
|
this.labelTrayIcon.AutoSize = true;
|
||||||
this.labelTrayIcon.Location = new System.Drawing.Point(6, 52);
|
this.labelTrayIcon.Location = new System.Drawing.Point(3, 38);
|
||||||
this.labelTrayIcon.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
this.labelTrayIcon.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
||||||
this.labelTrayIcon.Name = "labelTrayIcon";
|
this.labelTrayIcon.Name = "labelTrayIcon";
|
||||||
this.labelTrayIcon.Size = new System.Drawing.Size(52, 13);
|
this.labelTrayIcon.Size = new System.Drawing.Size(52, 13);
|
||||||
this.labelTrayIcon.TabIndex = 14;
|
this.labelTrayIcon.TabIndex = 1;
|
||||||
this.labelTrayIcon.Text = "Tray Icon";
|
this.labelTrayIcon.Text = "Tray Icon";
|
||||||
//
|
//
|
||||||
// groupInterface
|
// trackBarZoom
|
||||||
//
|
//
|
||||||
this.groupInterface.Controls.Add(this.checkSpellCheck);
|
this.trackBarZoom.AutoSize = false;
|
||||||
this.groupInterface.Controls.Add(this.checkExpandLinks);
|
this.trackBarZoom.BackColor = System.Drawing.SystemColors.Control;
|
||||||
this.groupInterface.Location = new System.Drawing.Point(9, 9);
|
this.trackBarZoom.LargeChange = 25;
|
||||||
this.groupInterface.Name = "groupInterface";
|
this.trackBarZoom.Location = new System.Drawing.Point(3, 122);
|
||||||
this.groupInterface.Size = new System.Drawing.Size(183, 71);
|
this.trackBarZoom.Maximum = 200;
|
||||||
this.groupInterface.TabIndex = 16;
|
this.trackBarZoom.Minimum = 50;
|
||||||
this.groupInterface.TabStop = false;
|
this.trackBarZoom.Name = "trackBarZoom";
|
||||||
this.groupInterface.Text = "User Interface";
|
this.trackBarZoom.Size = new System.Drawing.Size(148, 30);
|
||||||
|
this.trackBarZoom.SmallChange = 5;
|
||||||
|
this.trackBarZoom.TabIndex = 5;
|
||||||
|
this.trackBarZoom.TickFrequency = 25;
|
||||||
|
this.trackBarZoom.Value = 100;
|
||||||
|
//
|
||||||
|
// labelZoom
|
||||||
|
//
|
||||||
|
this.labelZoom.AutoSize = true;
|
||||||
|
this.labelZoom.Location = new System.Drawing.Point(3, 106);
|
||||||
|
this.labelZoom.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelZoom.Name = "labelZoom";
|
||||||
|
this.labelZoom.Size = new System.Drawing.Size(34, 13);
|
||||||
|
this.labelZoom.TabIndex = 4;
|
||||||
|
this.labelZoom.Text = "Zoom";
|
||||||
|
//
|
||||||
|
// zoomUpdateTimer
|
||||||
|
//
|
||||||
|
this.zoomUpdateTimer.Interval = 250;
|
||||||
|
this.zoomUpdateTimer.Tick += new System.EventHandler(this.zoomUpdateTimer_Tick);
|
||||||
|
//
|
||||||
|
// labelUI
|
||||||
|
//
|
||||||
|
this.labelUI.AutoSize = true;
|
||||||
|
this.labelUI.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelUI.Location = new System.Drawing.Point(6, 8);
|
||||||
|
this.labelUI.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||||
|
this.labelUI.Name = "labelUI";
|
||||||
|
this.labelUI.Size = new System.Drawing.Size(111, 20);
|
||||||
|
this.labelUI.TabIndex = 0;
|
||||||
|
this.labelUI.Text = "User Interface";
|
||||||
|
//
|
||||||
|
// panelUI
|
||||||
|
//
|
||||||
|
this.panelUI.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelUI.Controls.Add(this.checkBestImageQuality);
|
||||||
|
this.panelUI.Controls.Add(this.checkExpandLinks);
|
||||||
|
this.panelUI.Controls.Add(this.checkSwitchAccountSelectors);
|
||||||
|
this.panelUI.Controls.Add(this.checkSpellCheck);
|
||||||
|
this.panelUI.Controls.Add(this.labelZoom);
|
||||||
|
this.panelUI.Controls.Add(this.labelZoomValue);
|
||||||
|
this.panelUI.Controls.Add(this.trackBarZoom);
|
||||||
|
this.panelUI.Location = new System.Drawing.Point(9, 31);
|
||||||
|
this.panelUI.Name = "panelUI";
|
||||||
|
this.panelUI.Size = new System.Drawing.Size(322, 157);
|
||||||
|
this.panelUI.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// labelTray
|
||||||
|
//
|
||||||
|
this.labelTray.AutoSize = true;
|
||||||
|
this.labelTray.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelTray.Location = new System.Drawing.Point(6, 212);
|
||||||
|
this.labelTray.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelTray.Name = "labelTray";
|
||||||
|
this.labelTray.Size = new System.Drawing.Size(96, 20);
|
||||||
|
this.labelTray.TabIndex = 2;
|
||||||
|
this.labelTray.Text = "System Tray";
|
||||||
|
//
|
||||||
|
// panelUpdates
|
||||||
|
//
|
||||||
|
this.panelUpdates.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelUpdates.Controls.Add(this.checkUpdateNotifications);
|
||||||
|
this.panelUpdates.Controls.Add(this.btnCheckUpdates);
|
||||||
|
this.panelUpdates.Location = new System.Drawing.Point(9, 358);
|
||||||
|
this.panelUpdates.Name = "panelUpdates";
|
||||||
|
this.panelUpdates.Size = new System.Drawing.Size(322, 55);
|
||||||
|
this.panelUpdates.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// panelTray
|
||||||
|
//
|
||||||
|
this.panelTray.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelTray.Controls.Add(this.checkTrayHighlight);
|
||||||
|
this.panelTray.Controls.Add(this.comboBoxTrayType);
|
||||||
|
this.panelTray.Controls.Add(this.labelTrayIcon);
|
||||||
|
this.panelTray.Location = new System.Drawing.Point(9, 235);
|
||||||
|
this.panelTray.Name = "panelTray";
|
||||||
|
this.panelTray.Size = new System.Drawing.Size(322, 76);
|
||||||
|
this.panelTray.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// labelUpdates
|
||||||
|
//
|
||||||
|
this.labelUpdates.AutoSize = true;
|
||||||
|
this.labelUpdates.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelUpdates.Location = new System.Drawing.Point(6, 335);
|
||||||
|
this.labelUpdates.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelUpdates.Name = "labelUpdates";
|
||||||
|
this.labelUpdates.Size = new System.Drawing.Size(70, 20);
|
||||||
|
this.labelUpdates.TabIndex = 4;
|
||||||
|
this.labelUpdates.Text = "Updates";
|
||||||
|
//
|
||||||
|
// checkBestImageQuality
|
||||||
|
//
|
||||||
|
this.checkBestImageQuality.AutoSize = true;
|
||||||
|
this.checkBestImageQuality.Location = new System.Drawing.Point(6, 51);
|
||||||
|
this.checkBestImageQuality.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkBestImageQuality.Name = "checkBestImageQuality";
|
||||||
|
this.checkBestImageQuality.Size = new System.Drawing.Size(114, 17);
|
||||||
|
this.checkBestImageQuality.TabIndex = 2;
|
||||||
|
this.checkBestImageQuality.Text = "Best Image Quality";
|
||||||
|
this.toolTip.SetToolTip(this.checkBestImageQuality, "When right-clicking a tweet image, the context menu options\r\nwill use links to the original image size (:orig in the URL).");
|
||||||
|
this.checkBestImageQuality.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// TabSettingsGeneral
|
// TabSettingsGeneral
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.Controls.Add(this.groupInterface);
|
this.Controls.Add(this.labelUpdates);
|
||||||
this.Controls.Add(this.groupTray);
|
this.Controls.Add(this.panelTray);
|
||||||
|
this.Controls.Add(this.panelUpdates);
|
||||||
|
this.Controls.Add(this.labelTray);
|
||||||
|
this.Controls.Add(this.panelUI);
|
||||||
|
this.Controls.Add(this.labelUI);
|
||||||
this.Name = "TabSettingsGeneral";
|
this.Name = "TabSettingsGeneral";
|
||||||
this.Size = new System.Drawing.Size(478, 282);
|
this.Size = new System.Drawing.Size(340, 422);
|
||||||
this.groupTray.ResumeLayout(false);
|
((System.ComponentModel.ISupportInitialize)(this.trackBarZoom)).EndInit();
|
||||||
this.groupTray.PerformLayout();
|
this.panelUI.ResumeLayout(false);
|
||||||
this.groupInterface.ResumeLayout(false);
|
this.panelUI.PerformLayout();
|
||||||
this.groupInterface.PerformLayout();
|
this.panelUpdates.ResumeLayout(false);
|
||||||
|
this.panelUpdates.PerformLayout();
|
||||||
|
this.panelTray.ResumeLayout(false);
|
||||||
|
this.panelTray.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,10 +297,22 @@
|
|||||||
private System.Windows.Forms.CheckBox checkExpandLinks;
|
private System.Windows.Forms.CheckBox checkExpandLinks;
|
||||||
private System.Windows.Forms.ComboBox comboBoxTrayType;
|
private System.Windows.Forms.ComboBox comboBoxTrayType;
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
private System.Windows.Forms.GroupBox groupTray;
|
|
||||||
private System.Windows.Forms.GroupBox groupInterface;
|
|
||||||
private System.Windows.Forms.Label labelTrayIcon;
|
private System.Windows.Forms.Label labelTrayIcon;
|
||||||
private System.Windows.Forms.CheckBox checkTrayHighlight;
|
private System.Windows.Forms.CheckBox checkTrayHighlight;
|
||||||
private System.Windows.Forms.CheckBox checkSpellCheck;
|
private System.Windows.Forms.CheckBox checkSpellCheck;
|
||||||
|
private System.Windows.Forms.CheckBox checkUpdateNotifications;
|
||||||
|
private System.Windows.Forms.Button btnCheckUpdates;
|
||||||
|
private System.Windows.Forms.Label labelZoom;
|
||||||
|
private System.Windows.Forms.Label labelZoomValue;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarZoom;
|
||||||
|
private System.Windows.Forms.Timer zoomUpdateTimer;
|
||||||
|
private System.Windows.Forms.CheckBox checkSwitchAccountSelectors;
|
||||||
|
private System.Windows.Forms.Label labelUI;
|
||||||
|
private System.Windows.Forms.Panel panelUI;
|
||||||
|
private System.Windows.Forms.Label labelTray;
|
||||||
|
private System.Windows.Forms.Panel panelUpdates;
|
||||||
|
private System.Windows.Forms.Panel panelTray;
|
||||||
|
private System.Windows.Forms.Label labelUpdates;
|
||||||
|
private System.Windows.Forms.CheckBox checkBestImageQuality;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using TweetDuck.Core.Controls;
|
||||||
|
using TweetDuck.Updates;
|
||||||
|
using TweetDuck.Updates.Events;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
partial class TabSettingsGeneral : BaseTabSettings{
|
partial class TabSettingsGeneral : BaseTabSettings{
|
||||||
public TabSettingsGeneral(){
|
private readonly UpdateHandler updates;
|
||||||
|
private int updateCheckEventId = -1;
|
||||||
|
|
||||||
|
public TabSettingsGeneral(UpdateHandler updates){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
this.updates = updates;
|
||||||
|
this.updates.CheckFinished += updates_CheckFinished;
|
||||||
|
Disposed += (sender, args) => this.updates.CheckFinished -= updates_CheckFinished;
|
||||||
|
|
||||||
comboBoxTrayType.Items.Add("Disabled");
|
comboBoxTrayType.Items.Add("Disabled");
|
||||||
comboBoxTrayType.Items.Add("Display Icon Only");
|
comboBoxTrayType.Items.Add("Display Icon Only");
|
||||||
comboBoxTrayType.Items.Add("Minimize to Tray");
|
comboBoxTrayType.Items.Add("Minimize to Tray");
|
||||||
@@ -12,34 +22,101 @@ namespace TweetDck.Core.Other.Settings{
|
|||||||
comboBoxTrayType.Items.Add("Combined");
|
comboBoxTrayType.Items.Add("Combined");
|
||||||
comboBoxTrayType.SelectedIndex = Math.Min(Math.Max((int)Config.TrayBehavior, 0), comboBoxTrayType.Items.Count-1);
|
comboBoxTrayType.SelectedIndex = Math.Min(Math.Max((int)Config.TrayBehavior, 0), comboBoxTrayType.Items.Count-1);
|
||||||
|
|
||||||
|
toolTip.SetToolTip(trackBarZoom, toolTip.GetToolTip(labelZoomValue));
|
||||||
|
trackBarZoom.SetValueSafe(Config.ZoomLevel);
|
||||||
|
labelZoomValue.Text = trackBarZoom.Value+"%";
|
||||||
|
|
||||||
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
|
checkExpandLinks.Checked = Config.ExpandLinksOnHover;
|
||||||
|
checkSwitchAccountSelectors.Checked = Config.SwitchAccountSelectors;
|
||||||
|
checkBestImageQuality.Checked = Config.BestImageQuality;
|
||||||
checkSpellCheck.Checked = Config.EnableSpellCheck;
|
checkSpellCheck.Checked = Config.EnableSpellCheck;
|
||||||
checkTrayHighlight.Checked = Config.EnableTrayHighlight;
|
checkTrayHighlight.Checked = Config.EnableTrayHighlight;
|
||||||
|
|
||||||
|
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
checkExpandLinks.CheckedChanged += checkExpandLinks_CheckedChanged;
|
||||||
|
checkSwitchAccountSelectors.CheckedChanged += checkSwitchAccountSelectors_CheckedChanged;
|
||||||
|
checkBestImageQuality.CheckedChanged += checkBestImageQuality_CheckedChanged;
|
||||||
|
checkSpellCheck.CheckedChanged += checkSpellCheck_CheckedChanged;
|
||||||
|
trackBarZoom.ValueChanged += trackBarZoom_ValueChanged;
|
||||||
|
|
||||||
|
comboBoxTrayType.SelectedIndexChanged += comboBoxTrayType_SelectedIndexChanged;
|
||||||
|
checkTrayHighlight.CheckedChanged += checkTrayHighlight_CheckedChanged;
|
||||||
|
|
||||||
|
checkUpdateNotifications.CheckedChanged += checkUpdateNotifications_CheckedChanged;
|
||||||
|
btnCheckUpdates.Click += btnCheckUpdates_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
Config.ZoomLevel = trackBarZoom.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkExpandLinks_CheckedChanged(object sender, EventArgs e){
|
private void checkExpandLinks_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.ExpandLinksOnHover = checkExpandLinks.Checked;
|
Config.ExpandLinksOnHover = checkExpandLinks.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
|
private void checkSwitchAccountSelectors_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
Config.SwitchAccountSelectors = checkSwitchAccountSelectors.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkBestImageQuality_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.BestImageQuality = checkBestImageQuality.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSpellCheck_CheckedChanged(object sender, EventArgs e){
|
||||||
Config.EnableSpellCheck = checkSpellCheck.Checked;
|
Config.EnableSpellCheck = checkSpellCheck.Checked;
|
||||||
PromptRestart();
|
PromptRestart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void comboBoxTrayType_SelectedIndexChanged(object sender, EventArgs e){
|
private void trackBarZoom_ValueChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
if (trackBarZoom.AlignValueToTick()){
|
||||||
|
zoomUpdateTimer.Stop();
|
||||||
|
zoomUpdateTimer.Start();
|
||||||
|
labelZoomValue.Text = trackBarZoom.Value+"%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxTrayType_SelectedIndexChanged(object sender, EventArgs e){
|
||||||
Config.TrayBehavior = (TrayIcon.Behavior)comboBoxTrayType.SelectedIndex;
|
Config.TrayBehavior = (TrayIcon.Behavior)comboBoxTrayType.SelectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTrayHighlight_CheckedChanged(object sender, EventArgs e){
|
private void checkTrayHighlight_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.EnableTrayHighlight = checkTrayHighlight.Checked;
|
Config.EnableTrayHighlight = checkTrayHighlight.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.EnableUpdateCheck = checkUpdateNotifications.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCheckUpdates_Click(object sender, EventArgs e){
|
||||||
|
updateCheckEventId = updates.Check(true);
|
||||||
|
|
||||||
|
if (updateCheckEventId == -1){
|
||||||
|
FormMessage.Warning("Unsupported System", "Sorry, your system is no longer supported.", FormMessage.OK);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
btnCheckUpdates.Enabled = false;
|
||||||
|
updates.DismissUpdate(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||||
|
this.InvokeAsyncSafe(() => {
|
||||||
|
if (e.EventId == updateCheckEventId){
|
||||||
|
btnCheckUpdates.Enabled = true;
|
||||||
|
|
||||||
|
if (!e.UpdateAvailable){
|
||||||
|
FormMessage.Information("No Updates Available", "Your version of TweetDuck is up to date.", FormMessage.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zoomUpdateTimer_Tick(object sender, EventArgs e){
|
||||||
|
Config.ZoomLevel = trackBarZoom.Value;
|
||||||
|
zoomUpdateTimer.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
517
Core/Other/Settings/TabSettingsNotifications.Designer.cs
generated
517
Core/Other/Settings/TabSettingsNotifications.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core.Other.Settings {
|
namespace TweetDuck.Core.Other.Settings {
|
||||||
partial class TabSettingsNotifications {
|
partial class TabSettingsNotifications {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.groupNotificationLocation = new System.Windows.Forms.GroupBox();
|
|
||||||
this.labelEdgeDistanceValue = new System.Windows.Forms.Label();
|
this.labelEdgeDistanceValue = new System.Windows.Forms.Label();
|
||||||
this.labelDisplay = new System.Windows.Forms.Label();
|
this.labelDisplay = new System.Windows.Forms.Label();
|
||||||
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
this.comboBoxDisplay = new System.Windows.Forms.ComboBox();
|
||||||
@@ -35,64 +34,64 @@
|
|||||||
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
this.radioLocTR = new System.Windows.Forms.RadioButton();
|
||||||
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
this.radioLocTL = new System.Windows.Forms.RadioButton();
|
||||||
this.trackBarEdgeDistance = new System.Windows.Forms.TrackBar();
|
this.trackBarEdgeDistance = new System.Windows.Forms.TrackBar();
|
||||||
this.groupNotificationDuration = new System.Windows.Forms.GroupBox();
|
|
||||||
this.tableLayoutDurationButtons = new System.Windows.Forms.TableLayoutPanel();
|
this.tableLayoutDurationButtons = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.btnDurationMedium = new TweetDck.Core.Controls.FlatButton();
|
this.btnDurationMedium = new TweetDuck.Core.Controls.FlatButton();
|
||||||
this.btnDurationLong = new TweetDck.Core.Controls.FlatButton();
|
this.btnDurationLong = new TweetDuck.Core.Controls.FlatButton();
|
||||||
this.btnDurationShort = new TweetDck.Core.Controls.FlatButton();
|
this.btnDurationShort = new TweetDuck.Core.Controls.FlatButton();
|
||||||
this.labelDurationValue = new System.Windows.Forms.Label();
|
this.labelDurationValue = new System.Windows.Forms.Label();
|
||||||
this.trackBarDuration = new System.Windows.Forms.TrackBar();
|
this.trackBarDuration = new System.Windows.Forms.TrackBar();
|
||||||
this.groupUserInterface = new System.Windows.Forms.GroupBox();
|
this.checkSkipOnLinkClick = new System.Windows.Forms.CheckBox();
|
||||||
|
this.checkColumnName = new System.Windows.Forms.CheckBox();
|
||||||
|
this.labelIdlePause = new System.Windows.Forms.Label();
|
||||||
|
this.comboBoxIdlePause = new System.Windows.Forms.ComboBox();
|
||||||
|
this.checkNonIntrusive = new System.Windows.Forms.CheckBox();
|
||||||
this.checkTimerCountDown = new System.Windows.Forms.CheckBox();
|
this.checkTimerCountDown = new System.Windows.Forms.CheckBox();
|
||||||
this.checkLegacyLoad = new System.Windows.Forms.CheckBox();
|
|
||||||
this.checkNotificationTimer = new System.Windows.Forms.CheckBox();
|
this.checkNotificationTimer = new System.Windows.Forms.CheckBox();
|
||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
this.groupNotificationLocation.SuspendLayout();
|
this.radioSizeAuto = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioSizeCustom = new System.Windows.Forms.RadioButton();
|
||||||
|
this.labelGeneral = new System.Windows.Forms.Label();
|
||||||
|
this.panelGeneral = new System.Windows.Forms.Panel();
|
||||||
|
this.labelScrollSpeedValue = new System.Windows.Forms.Label();
|
||||||
|
this.trackBarScrollSpeed = new System.Windows.Forms.TrackBar();
|
||||||
|
this.labelScrollSpeed = new System.Windows.Forms.Label();
|
||||||
|
this.labelLocation = new System.Windows.Forms.Label();
|
||||||
|
this.panelLocation = new System.Windows.Forms.Panel();
|
||||||
|
this.panelTimer = new System.Windows.Forms.Panel();
|
||||||
|
this.labelDuration = new System.Windows.Forms.Label();
|
||||||
|
this.labelTimer = new System.Windows.Forms.Label();
|
||||||
|
this.labelSize = new System.Windows.Forms.Label();
|
||||||
|
this.panelMiscellaneous = new System.Windows.Forms.Panel();
|
||||||
|
this.durationUpdateTimer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.checkMediaPreviews = new System.Windows.Forms.CheckBox();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).BeginInit();
|
||||||
this.groupNotificationDuration.SuspendLayout();
|
|
||||||
this.tableLayoutDurationButtons.SuspendLayout();
|
this.tableLayoutDurationButtons.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).BeginInit();
|
||||||
this.groupUserInterface.SuspendLayout();
|
this.panelGeneral.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).BeginInit();
|
||||||
|
this.panelLocation.SuspendLayout();
|
||||||
|
this.panelTimer.SuspendLayout();
|
||||||
|
this.panelMiscellaneous.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// groupNotificationLocation
|
|
||||||
//
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.labelEdgeDistanceValue);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.labelDisplay);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.comboBoxDisplay);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.labelEdgeDistance);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocCustom);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocBR);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocBL);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocTR);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.radioLocTL);
|
|
||||||
this.groupNotificationLocation.Controls.Add(this.trackBarEdgeDistance);
|
|
||||||
this.groupNotificationLocation.Location = new System.Drawing.Point(198, 9);
|
|
||||||
this.groupNotificationLocation.Name = "groupNotificationLocation";
|
|
||||||
this.groupNotificationLocation.Size = new System.Drawing.Size(183, 264);
|
|
||||||
this.groupNotificationLocation.TabIndex = 1;
|
|
||||||
this.groupNotificationLocation.TabStop = false;
|
|
||||||
this.groupNotificationLocation.Text = "Location";
|
|
||||||
//
|
|
||||||
// labelEdgeDistanceValue
|
// labelEdgeDistanceValue
|
||||||
//
|
//
|
||||||
this.labelEdgeDistanceValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.labelEdgeDistanceValue.Location = new System.Drawing.Point(147, 129);
|
||||||
this.labelEdgeDistanceValue.Location = new System.Drawing.Point(143, 214);
|
|
||||||
this.labelEdgeDistanceValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
this.labelEdgeDistanceValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
this.labelEdgeDistanceValue.Name = "labelEdgeDistanceValue";
|
this.labelEdgeDistanceValue.Name = "labelEdgeDistanceValue";
|
||||||
this.labelEdgeDistanceValue.Size = new System.Drawing.Size(34, 13);
|
this.labelEdgeDistanceValue.Size = new System.Drawing.Size(34, 13);
|
||||||
this.labelEdgeDistanceValue.TabIndex = 11;
|
this.labelEdgeDistanceValue.TabIndex = 9;
|
||||||
this.labelEdgeDistanceValue.Text = "0 px";
|
this.labelEdgeDistanceValue.Text = "0 px";
|
||||||
this.labelEdgeDistanceValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
this.labelEdgeDistanceValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
//
|
//
|
||||||
// labelDisplay
|
// labelDisplay
|
||||||
//
|
//
|
||||||
this.labelDisplay.AutoSize = true;
|
this.labelDisplay.AutoSize = true;
|
||||||
this.labelDisplay.Location = new System.Drawing.Point(3, 148);
|
this.labelDisplay.Location = new System.Drawing.Point(3, 60);
|
||||||
this.labelDisplay.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
this.labelDisplay.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
this.labelDisplay.Name = "labelDisplay";
|
this.labelDisplay.Name = "labelDisplay";
|
||||||
this.labelDisplay.Size = new System.Drawing.Size(41, 13);
|
this.labelDisplay.Size = new System.Drawing.Size(41, 13);
|
||||||
this.labelDisplay.TabIndex = 8;
|
this.labelDisplay.TabIndex = 5;
|
||||||
this.labelDisplay.Text = "Display";
|
this.labelDisplay.Text = "Display";
|
||||||
//
|
//
|
||||||
// comboBoxDisplay
|
// comboBoxDisplay
|
||||||
@@ -101,115 +100,94 @@
|
|||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.comboBoxDisplay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
this.comboBoxDisplay.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
this.comboBoxDisplay.FormattingEnabled = true;
|
this.comboBoxDisplay.FormattingEnabled = true;
|
||||||
this.comboBoxDisplay.Location = new System.Drawing.Point(6, 164);
|
this.comboBoxDisplay.Location = new System.Drawing.Point(5, 76);
|
||||||
|
this.comboBoxDisplay.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
this.comboBoxDisplay.Name = "comboBoxDisplay";
|
this.comboBoxDisplay.Name = "comboBoxDisplay";
|
||||||
this.comboBoxDisplay.Size = new System.Drawing.Size(171, 21);
|
this.comboBoxDisplay.Size = new System.Drawing.Size(144, 21);
|
||||||
this.comboBoxDisplay.TabIndex = 7;
|
this.comboBoxDisplay.TabIndex = 6;
|
||||||
this.comboBoxDisplay.SelectedValueChanged += new System.EventHandler(this.comboBoxDisplay_SelectedValueChanged);
|
|
||||||
//
|
//
|
||||||
// labelEdgeDistance
|
// labelEdgeDistance
|
||||||
//
|
//
|
||||||
this.labelEdgeDistance.AutoSize = true;
|
this.labelEdgeDistance.AutoSize = true;
|
||||||
this.labelEdgeDistance.Location = new System.Drawing.Point(3, 197);
|
this.labelEdgeDistance.Location = new System.Drawing.Point(3, 112);
|
||||||
this.labelEdgeDistance.Margin = new System.Windows.Forms.Padding(3, 9, 3, 0);
|
this.labelEdgeDistance.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
this.labelEdgeDistance.Name = "labelEdgeDistance";
|
this.labelEdgeDistance.Name = "labelEdgeDistance";
|
||||||
this.labelEdgeDistance.Size = new System.Drawing.Size(103, 13);
|
this.labelEdgeDistance.Size = new System.Drawing.Size(103, 13);
|
||||||
this.labelEdgeDistance.TabIndex = 6;
|
this.labelEdgeDistance.TabIndex = 7;
|
||||||
this.labelEdgeDistance.Text = "Distance From Edge";
|
this.labelEdgeDistance.Text = "Distance From Edge";
|
||||||
//
|
//
|
||||||
// radioLocCustom
|
// radioLocCustom
|
||||||
//
|
//
|
||||||
this.radioLocCustom.AutoSize = true;
|
this.radioLocCustom.Location = new System.Drawing.Point(205, 4);
|
||||||
this.radioLocCustom.Location = new System.Drawing.Point(7, 116);
|
this.radioLocCustom.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
this.radioLocCustom.Name = "radioLocCustom";
|
this.radioLocCustom.Name = "radioLocCustom";
|
||||||
this.radioLocCustom.Size = new System.Drawing.Size(60, 17);
|
this.radioLocCustom.Size = new System.Drawing.Size(65, 41);
|
||||||
this.radioLocCustom.TabIndex = 4;
|
this.radioLocCustom.TabIndex = 4;
|
||||||
this.radioLocCustom.TabStop = true;
|
this.radioLocCustom.TabStop = true;
|
||||||
this.radioLocCustom.Text = "Custom";
|
this.radioLocCustom.Text = "Custom";
|
||||||
this.toolTip.SetToolTip(this.radioLocCustom, "Drag the notification window to the desired location.");
|
this.toolTip.SetToolTip(this.radioLocCustom, "Drag the example notification window to the desired location.");
|
||||||
this.radioLocCustom.UseVisualStyleBackColor = true;
|
this.radioLocCustom.UseVisualStyleBackColor = true;
|
||||||
this.radioLocCustom.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// radioLocBR
|
// radioLocBR
|
||||||
//
|
//
|
||||||
this.radioLocBR.AutoSize = true;
|
this.radioLocBR.Location = new System.Drawing.Point(105, 28);
|
||||||
this.radioLocBR.Location = new System.Drawing.Point(7, 92);
|
this.radioLocBR.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
this.radioLocBR.Name = "radioLocBR";
|
this.radioLocBR.Name = "radioLocBR";
|
||||||
this.radioLocBR.Size = new System.Drawing.Size(86, 17);
|
this.radioLocBR.Size = new System.Drawing.Size(92, 17);
|
||||||
this.radioLocBR.TabIndex = 3;
|
this.radioLocBR.TabIndex = 3;
|
||||||
this.radioLocBR.TabStop = true;
|
this.radioLocBR.TabStop = true;
|
||||||
this.radioLocBR.Text = "Bottom Right";
|
this.radioLocBR.Text = "Bottom Right";
|
||||||
this.radioLocBR.UseVisualStyleBackColor = true;
|
this.radioLocBR.UseVisualStyleBackColor = true;
|
||||||
this.radioLocBR.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// radioLocBL
|
// radioLocBL
|
||||||
//
|
//
|
||||||
this.radioLocBL.AutoSize = true;
|
this.radioLocBL.Location = new System.Drawing.Point(5, 28);
|
||||||
this.radioLocBL.Location = new System.Drawing.Point(7, 68);
|
this.radioLocBL.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
this.radioLocBL.Name = "radioLocBL";
|
this.radioLocBL.Name = "radioLocBL";
|
||||||
this.radioLocBL.Size = new System.Drawing.Size(79, 17);
|
this.radioLocBL.Size = new System.Drawing.Size(92, 17);
|
||||||
this.radioLocBL.TabIndex = 2;
|
this.radioLocBL.TabIndex = 2;
|
||||||
this.radioLocBL.TabStop = true;
|
this.radioLocBL.TabStop = true;
|
||||||
this.radioLocBL.Text = "Bottom Left";
|
this.radioLocBL.Text = "Bottom Left";
|
||||||
this.radioLocBL.UseVisualStyleBackColor = true;
|
this.radioLocBL.UseVisualStyleBackColor = true;
|
||||||
this.radioLocBL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// radioLocTR
|
// radioLocTR
|
||||||
//
|
//
|
||||||
this.radioLocTR.AutoSize = true;
|
this.radioLocTR.Location = new System.Drawing.Point(105, 4);
|
||||||
this.radioLocTR.Location = new System.Drawing.Point(7, 44);
|
this.radioLocTR.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
this.radioLocTR.Name = "radioLocTR";
|
this.radioLocTR.Name = "radioLocTR";
|
||||||
this.radioLocTR.Size = new System.Drawing.Size(72, 17);
|
this.radioLocTR.Size = new System.Drawing.Size(92, 17);
|
||||||
this.radioLocTR.TabIndex = 1;
|
this.radioLocTR.TabIndex = 1;
|
||||||
this.radioLocTR.TabStop = true;
|
this.radioLocTR.TabStop = true;
|
||||||
this.radioLocTR.Text = "Top Right";
|
this.radioLocTR.Text = "Top Right";
|
||||||
this.radioLocTR.UseVisualStyleBackColor = true;
|
this.radioLocTR.UseVisualStyleBackColor = true;
|
||||||
this.radioLocTR.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// radioLocTL
|
// radioLocTL
|
||||||
//
|
//
|
||||||
this.radioLocTL.AutoSize = true;
|
this.radioLocTL.Location = new System.Drawing.Point(5, 4);
|
||||||
this.radioLocTL.Location = new System.Drawing.Point(7, 20);
|
this.radioLocTL.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
this.radioLocTL.Name = "radioLocTL";
|
this.radioLocTL.Name = "radioLocTL";
|
||||||
this.radioLocTL.Size = new System.Drawing.Size(65, 17);
|
this.radioLocTL.Size = new System.Drawing.Size(92, 17);
|
||||||
this.radioLocTL.TabIndex = 0;
|
this.radioLocTL.TabIndex = 0;
|
||||||
this.radioLocTL.TabStop = true;
|
this.radioLocTL.TabStop = true;
|
||||||
this.radioLocTL.Text = "Top Left";
|
this.radioLocTL.Text = "Top Left";
|
||||||
this.radioLocTL.UseVisualStyleBackColor = true;
|
this.radioLocTL.UseVisualStyleBackColor = true;
|
||||||
this.radioLocTL.CheckedChanged += new System.EventHandler(this.radioLoc_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// trackBarEdgeDistance
|
// trackBarEdgeDistance
|
||||||
//
|
//
|
||||||
this.trackBarEdgeDistance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.trackBarEdgeDistance.AutoSize = false;
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.trackBarEdgeDistance.LargeChange = 8;
|
this.trackBarEdgeDistance.LargeChange = 8;
|
||||||
this.trackBarEdgeDistance.Location = new System.Drawing.Point(6, 213);
|
this.trackBarEdgeDistance.Location = new System.Drawing.Point(5, 128);
|
||||||
this.trackBarEdgeDistance.Maximum = 40;
|
this.trackBarEdgeDistance.Maximum = 40;
|
||||||
this.trackBarEdgeDistance.Minimum = 8;
|
this.trackBarEdgeDistance.Minimum = 8;
|
||||||
this.trackBarEdgeDistance.Name = "trackBarEdgeDistance";
|
this.trackBarEdgeDistance.Name = "trackBarEdgeDistance";
|
||||||
this.trackBarEdgeDistance.Size = new System.Drawing.Size(141, 45);
|
this.trackBarEdgeDistance.Size = new System.Drawing.Size(148, 30);
|
||||||
this.trackBarEdgeDistance.SmallChange = 2;
|
this.trackBarEdgeDistance.SmallChange = 2;
|
||||||
this.trackBarEdgeDistance.TabIndex = 5;
|
this.trackBarEdgeDistance.TabIndex = 8;
|
||||||
this.trackBarEdgeDistance.TickFrequency = 4;
|
this.trackBarEdgeDistance.TickFrequency = 4;
|
||||||
this.trackBarEdgeDistance.Value = 8;
|
this.trackBarEdgeDistance.Value = 8;
|
||||||
this.trackBarEdgeDistance.ValueChanged += new System.EventHandler(this.trackBarEdgeDistance_ValueChanged);
|
|
||||||
//
|
|
||||||
// groupNotificationDuration
|
|
||||||
//
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.tableLayoutDurationButtons);
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.labelDurationValue);
|
|
||||||
this.groupNotificationDuration.Controls.Add(this.trackBarDuration);
|
|
||||||
this.groupNotificationDuration.Location = new System.Drawing.Point(9, 106);
|
|
||||||
this.groupNotificationDuration.Name = "groupNotificationDuration";
|
|
||||||
this.groupNotificationDuration.Size = new System.Drawing.Size(183, 89);
|
|
||||||
this.groupNotificationDuration.TabIndex = 9;
|
|
||||||
this.groupNotificationDuration.TabStop = false;
|
|
||||||
this.groupNotificationDuration.Text = "Duration";
|
|
||||||
//
|
//
|
||||||
// tableLayoutDurationButtons
|
// tableLayoutDurationButtons
|
||||||
//
|
//
|
||||||
this.tableLayoutDurationButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.tableLayoutDurationButtons.ColumnCount = 3;
|
this.tableLayoutDurationButtons.ColumnCount = 3;
|
||||||
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 32F));
|
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 32F));
|
||||||
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 36F));
|
this.tableLayoutDurationButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 36F));
|
||||||
@@ -217,7 +195,7 @@
|
|||||||
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationMedium, 0, 0);
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationMedium, 0, 0);
|
||||||
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationLong, 1, 0);
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationLong, 1, 0);
|
||||||
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationShort, 0, 0);
|
this.tableLayoutDurationButtons.Controls.Add(this.btnDurationShort, 0, 0);
|
||||||
this.tableLayoutDurationButtons.Location = new System.Drawing.Point(6, 56);
|
this.tableLayoutDurationButtons.Location = new System.Drawing.Point(3, 113);
|
||||||
this.tableLayoutDurationButtons.Name = "tableLayoutDurationButtons";
|
this.tableLayoutDurationButtons.Name = "tableLayoutDurationButtons";
|
||||||
this.tableLayoutDurationButtons.RowCount = 1;
|
this.tableLayoutDurationButtons.RowCount = 1;
|
||||||
this.tableLayoutDurationButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
this.tableLayoutDurationButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||||
@@ -235,10 +213,9 @@
|
|||||||
this.btnDurationMedium.Margin = new System.Windows.Forms.Padding(1);
|
this.btnDurationMedium.Margin = new System.Windows.Forms.Padding(1);
|
||||||
this.btnDurationMedium.Name = "btnDurationMedium";
|
this.btnDurationMedium.Name = "btnDurationMedium";
|
||||||
this.btnDurationMedium.Size = new System.Drawing.Size(59, 25);
|
this.btnDurationMedium.Size = new System.Drawing.Size(59, 25);
|
||||||
this.btnDurationMedium.TabIndex = 2;
|
this.btnDurationMedium.TabIndex = 1;
|
||||||
this.btnDurationMedium.Text = "Medium";
|
this.btnDurationMedium.Text = "Medium";
|
||||||
this.btnDurationMedium.UseVisualStyleBackColor = true;
|
this.btnDurationMedium.UseVisualStyleBackColor = true;
|
||||||
this.btnDurationMedium.Click += new System.EventHandler(this.btnDurationMedium_Click);
|
|
||||||
//
|
//
|
||||||
// btnDurationLong
|
// btnDurationLong
|
||||||
//
|
//
|
||||||
@@ -251,10 +228,9 @@
|
|||||||
this.btnDurationLong.Margin = new System.Windows.Forms.Padding(1);
|
this.btnDurationLong.Margin = new System.Windows.Forms.Padding(1);
|
||||||
this.btnDurationLong.Name = "btnDurationLong";
|
this.btnDurationLong.Name = "btnDurationLong";
|
||||||
this.btnDurationLong.Size = new System.Drawing.Size(54, 25);
|
this.btnDurationLong.Size = new System.Drawing.Size(54, 25);
|
||||||
this.btnDurationLong.TabIndex = 1;
|
this.btnDurationLong.TabIndex = 2;
|
||||||
this.btnDurationLong.Text = "Long";
|
this.btnDurationLong.Text = "Long";
|
||||||
this.btnDurationLong.UseVisualStyleBackColor = true;
|
this.btnDurationLong.UseVisualStyleBackColor = true;
|
||||||
this.btnDurationLong.Click += new System.EventHandler(this.btnDurationLong_Click);
|
|
||||||
//
|
//
|
||||||
// btnDurationShort
|
// btnDurationShort
|
||||||
//
|
//
|
||||||
@@ -270,111 +246,336 @@
|
|||||||
this.btnDurationShort.TabIndex = 0;
|
this.btnDurationShort.TabIndex = 0;
|
||||||
this.btnDurationShort.Text = "Short";
|
this.btnDurationShort.Text = "Short";
|
||||||
this.btnDurationShort.UseVisualStyleBackColor = true;
|
this.btnDurationShort.UseVisualStyleBackColor = true;
|
||||||
this.btnDurationShort.Click += new System.EventHandler(this.btnDurationShort_Click);
|
|
||||||
//
|
//
|
||||||
// labelDurationValue
|
// labelDurationValue
|
||||||
//
|
//
|
||||||
this.labelDurationValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.labelDurationValue.BackColor = System.Drawing.Color.Transparent;
|
this.labelDurationValue.BackColor = System.Drawing.Color.Transparent;
|
||||||
this.labelDurationValue.Location = new System.Drawing.Point(129, 20);
|
this.labelDurationValue.Location = new System.Drawing.Point(147, 77);
|
||||||
this.labelDurationValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
this.labelDurationValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
this.labelDurationValue.Name = "labelDurationValue";
|
this.labelDurationValue.Name = "labelDurationValue";
|
||||||
this.labelDurationValue.Size = new System.Drawing.Size(48, 13);
|
this.labelDurationValue.Size = new System.Drawing.Size(48, 13);
|
||||||
this.labelDurationValue.TabIndex = 13;
|
this.labelDurationValue.TabIndex = 4;
|
||||||
this.labelDurationValue.Text = "0 ms/c";
|
this.labelDurationValue.Text = "0 ms/c";
|
||||||
this.labelDurationValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
this.labelDurationValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
this.toolTip.SetToolTip(this.labelDurationValue, "Milliseconds per character.");
|
this.toolTip.SetToolTip(this.labelDurationValue, "Milliseconds per character.");
|
||||||
//
|
//
|
||||||
// trackBarDuration
|
// trackBarDuration
|
||||||
//
|
//
|
||||||
this.trackBarDuration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.trackBarDuration.AutoSize = false;
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
this.trackBarDuration.Location = new System.Drawing.Point(3, 76);
|
||||||
this.trackBarDuration.Location = new System.Drawing.Point(6, 19);
|
|
||||||
this.trackBarDuration.Maximum = 60;
|
this.trackBarDuration.Maximum = 60;
|
||||||
this.trackBarDuration.Minimum = 10;
|
this.trackBarDuration.Minimum = 10;
|
||||||
this.trackBarDuration.Name = "trackBarDuration";
|
this.trackBarDuration.Name = "trackBarDuration";
|
||||||
this.trackBarDuration.Size = new System.Drawing.Size(128, 45);
|
this.trackBarDuration.Size = new System.Drawing.Size(148, 30);
|
||||||
this.trackBarDuration.TabIndex = 12;
|
this.trackBarDuration.TabIndex = 3;
|
||||||
this.trackBarDuration.TickFrequency = 5;
|
this.trackBarDuration.TickFrequency = 5;
|
||||||
this.trackBarDuration.Value = 25;
|
this.trackBarDuration.Value = 25;
|
||||||
this.trackBarDuration.ValueChanged += new System.EventHandler(this.trackBarDuration_ValueChanged);
|
|
||||||
//
|
//
|
||||||
// groupUserInterface
|
// checkSkipOnLinkClick
|
||||||
//
|
//
|
||||||
this.groupUserInterface.Controls.Add(this.checkTimerCountDown);
|
this.checkSkipOnLinkClick.AutoSize = true;
|
||||||
this.groupUserInterface.Controls.Add(this.checkLegacyLoad);
|
this.checkSkipOnLinkClick.Location = new System.Drawing.Point(6, 51);
|
||||||
this.groupUserInterface.Controls.Add(this.checkNotificationTimer);
|
this.checkSkipOnLinkClick.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
this.groupUserInterface.Location = new System.Drawing.Point(9, 9);
|
this.checkSkipOnLinkClick.Name = "checkSkipOnLinkClick";
|
||||||
this.groupUserInterface.Name = "groupUserInterface";
|
this.checkSkipOnLinkClick.Size = new System.Drawing.Size(113, 17);
|
||||||
this.groupUserInterface.Size = new System.Drawing.Size(183, 91);
|
this.checkSkipOnLinkClick.TabIndex = 2;
|
||||||
this.groupUserInterface.TabIndex = 10;
|
this.checkSkipOnLinkClick.Text = "Skip On Link Click";
|
||||||
this.groupUserInterface.TabStop = false;
|
this.toolTip.SetToolTip(this.checkSkipOnLinkClick, "Skips current notification when a link\r\ninside the notification is clicked.");
|
||||||
this.groupUserInterface.Text = "General";
|
this.checkSkipOnLinkClick.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// checkColumnName
|
||||||
|
//
|
||||||
|
this.checkColumnName.AutoSize = true;
|
||||||
|
this.checkColumnName.Location = new System.Drawing.Point(6, 5);
|
||||||
|
this.checkColumnName.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
|
this.checkColumnName.Name = "checkColumnName";
|
||||||
|
this.checkColumnName.Size = new System.Drawing.Size(129, 17);
|
||||||
|
this.checkColumnName.TabIndex = 0;
|
||||||
|
this.checkColumnName.Text = "Display Column Name";
|
||||||
|
this.toolTip.SetToolTip(this.checkColumnName, "Shows column name each notification originated\r\nfrom in the notification window title.");
|
||||||
|
this.checkColumnName.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelIdlePause
|
||||||
|
//
|
||||||
|
this.labelIdlePause.AutoSize = true;
|
||||||
|
this.labelIdlePause.Location = new System.Drawing.Point(3, 106);
|
||||||
|
this.labelIdlePause.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelIdlePause.Name = "labelIdlePause";
|
||||||
|
this.labelIdlePause.Size = new System.Drawing.Size(89, 13);
|
||||||
|
this.labelIdlePause.TabIndex = 4;
|
||||||
|
this.labelIdlePause.Text = "Pause When Idle";
|
||||||
|
//
|
||||||
|
// comboBoxIdlePause
|
||||||
|
//
|
||||||
|
this.comboBoxIdlePause.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.comboBoxIdlePause.FormattingEnabled = true;
|
||||||
|
this.comboBoxIdlePause.Location = new System.Drawing.Point(5, 122);
|
||||||
|
this.comboBoxIdlePause.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
|
||||||
|
this.comboBoxIdlePause.Name = "comboBoxIdlePause";
|
||||||
|
this.comboBoxIdlePause.Size = new System.Drawing.Size(144, 21);
|
||||||
|
this.comboBoxIdlePause.TabIndex = 5;
|
||||||
|
this.toolTip.SetToolTip(this.comboBoxIdlePause, "Pauses new notifications after going idle for a set amount of time.");
|
||||||
|
//
|
||||||
|
// checkNonIntrusive
|
||||||
|
//
|
||||||
|
this.checkNonIntrusive.AutoSize = true;
|
||||||
|
this.checkNonIntrusive.Location = new System.Drawing.Point(6, 74);
|
||||||
|
this.checkNonIntrusive.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkNonIntrusive.Name = "checkNonIntrusive";
|
||||||
|
this.checkNonIntrusive.Size = new System.Drawing.Size(128, 17);
|
||||||
|
this.checkNonIntrusive.TabIndex = 3;
|
||||||
|
this.checkNonIntrusive.Text = "Non-Intrusive Popups";
|
||||||
|
this.toolTip.SetToolTip(this.checkNonIntrusive, "When not idle and the cursor is within the notification window area,\r\nit will be delayed until the cursor moves away to prevent accidental clicks.");
|
||||||
|
this.checkNonIntrusive.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// checkTimerCountDown
|
// checkTimerCountDown
|
||||||
//
|
//
|
||||||
this.checkTimerCountDown.AutoSize = true;
|
this.checkTimerCountDown.AutoSize = true;
|
||||||
this.checkTimerCountDown.Location = new System.Drawing.Point(6, 44);
|
this.checkTimerCountDown.Location = new System.Drawing.Point(6, 28);
|
||||||
|
this.checkTimerCountDown.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
this.checkTimerCountDown.Name = "checkTimerCountDown";
|
this.checkTimerCountDown.Name = "checkTimerCountDown";
|
||||||
this.checkTimerCountDown.Size = new System.Drawing.Size(119, 17);
|
this.checkTimerCountDown.Size = new System.Drawing.Size(119, 17);
|
||||||
this.checkTimerCountDown.TabIndex = 6;
|
this.checkTimerCountDown.TabIndex = 1;
|
||||||
this.checkTimerCountDown.Text = "Timer Counts Down";
|
this.checkTimerCountDown.Text = "Timer Counts Down";
|
||||||
this.toolTip.SetToolTip(this.checkTimerCountDown, "The notification timer counts down instead of up.");
|
this.toolTip.SetToolTip(this.checkTimerCountDown, "The notification timer counts down instead of up.");
|
||||||
this.checkTimerCountDown.UseVisualStyleBackColor = true;
|
this.checkTimerCountDown.UseVisualStyleBackColor = true;
|
||||||
this.checkTimerCountDown.CheckedChanged += new System.EventHandler(this.checkTimerCountDown_CheckedChanged);
|
|
||||||
//
|
|
||||||
// checkLegacyLoad
|
|
||||||
//
|
|
||||||
this.checkLegacyLoad.AutoSize = true;
|
|
||||||
this.checkLegacyLoad.Location = new System.Drawing.Point(6, 67);
|
|
||||||
this.checkLegacyLoad.Name = "checkLegacyLoad";
|
|
||||||
this.checkLegacyLoad.Size = new System.Drawing.Size(139, 17);
|
|
||||||
this.checkLegacyLoad.TabIndex = 5;
|
|
||||||
this.checkLegacyLoad.Text = "Legacy Loading System";
|
|
||||||
this.toolTip.SetToolTip(this.checkLegacyLoad, "Try enabling if notifications do not display.\r\nMight cause delays and visual arti" +
|
|
||||||
"facts.");
|
|
||||||
this.checkLegacyLoad.UseVisualStyleBackColor = true;
|
|
||||||
this.checkLegacyLoad.CheckedChanged += new System.EventHandler(this.checkLegacyLoad_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// checkNotificationTimer
|
// checkNotificationTimer
|
||||||
//
|
//
|
||||||
this.checkNotificationTimer.AutoSize = true;
|
this.checkNotificationTimer.AutoSize = true;
|
||||||
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 21);
|
this.checkNotificationTimer.Location = new System.Drawing.Point(6, 5);
|
||||||
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
this.checkNotificationTimer.Margin = new System.Windows.Forms.Padding(6, 5, 3, 3);
|
||||||
this.checkNotificationTimer.Name = "checkNotificationTimer";
|
this.checkNotificationTimer.Name = "checkNotificationTimer";
|
||||||
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
|
this.checkNotificationTimer.Size = new System.Drawing.Size(145, 17);
|
||||||
this.checkNotificationTimer.TabIndex = 4;
|
this.checkNotificationTimer.TabIndex = 0;
|
||||||
this.checkNotificationTimer.Text = "Display Notification Timer";
|
this.checkNotificationTimer.Text = "Display Notification Timer";
|
||||||
this.toolTip.SetToolTip(this.checkNotificationTimer, "Shows how much time is left before the current notification disappears.");
|
|
||||||
this.checkNotificationTimer.UseVisualStyleBackColor = true;
|
this.checkNotificationTimer.UseVisualStyleBackColor = true;
|
||||||
this.checkNotificationTimer.CheckedChanged += new System.EventHandler(this.checkNotificationTimer_CheckedChanged);
|
//
|
||||||
|
// radioSizeAuto
|
||||||
|
//
|
||||||
|
this.radioSizeAuto.Location = new System.Drawing.Point(6, 4);
|
||||||
|
this.radioSizeAuto.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
|
this.radioSizeAuto.Name = "radioSizeAuto";
|
||||||
|
this.radioSizeAuto.Size = new System.Drawing.Size(92, 17);
|
||||||
|
this.radioSizeAuto.TabIndex = 0;
|
||||||
|
this.radioSizeAuto.TabStop = true;
|
||||||
|
this.radioSizeAuto.Text = "Auto";
|
||||||
|
this.toolTip.SetToolTip(this.radioSizeAuto, "Notification size is based on the font size and browser zoom level.");
|
||||||
|
this.radioSizeAuto.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioSizeCustom
|
||||||
|
//
|
||||||
|
this.radioSizeCustom.Location = new System.Drawing.Point(106, 4);
|
||||||
|
this.radioSizeCustom.Margin = new System.Windows.Forms.Padding(5, 4, 3, 3);
|
||||||
|
this.radioSizeCustom.Name = "radioSizeCustom";
|
||||||
|
this.radioSizeCustom.Size = new System.Drawing.Size(92, 17);
|
||||||
|
this.radioSizeCustom.TabIndex = 1;
|
||||||
|
this.radioSizeCustom.TabStop = true;
|
||||||
|
this.radioSizeCustom.Text = "Custom";
|
||||||
|
this.toolTip.SetToolTip(this.radioSizeCustom, "Resize the example notification window to the desired size.");
|
||||||
|
this.radioSizeCustom.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelGeneral
|
||||||
|
//
|
||||||
|
this.labelGeneral.AutoSize = true;
|
||||||
|
this.labelGeneral.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelGeneral.Location = new System.Drawing.Point(6, 8);
|
||||||
|
this.labelGeneral.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||||
|
this.labelGeneral.Name = "labelGeneral";
|
||||||
|
this.labelGeneral.Size = new System.Drawing.Size(66, 20);
|
||||||
|
this.labelGeneral.TabIndex = 0;
|
||||||
|
this.labelGeneral.Text = "General";
|
||||||
|
//
|
||||||
|
// panelGeneral
|
||||||
|
//
|
||||||
|
this.panelGeneral.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelGeneral.Controls.Add(this.checkMediaPreviews);
|
||||||
|
this.panelGeneral.Controls.Add(this.checkColumnName);
|
||||||
|
this.panelGeneral.Controls.Add(this.checkSkipOnLinkClick);
|
||||||
|
this.panelGeneral.Controls.Add(this.checkNonIntrusive);
|
||||||
|
this.panelGeneral.Controls.Add(this.labelIdlePause);
|
||||||
|
this.panelGeneral.Controls.Add(this.comboBoxIdlePause);
|
||||||
|
this.panelGeneral.Location = new System.Drawing.Point(9, 31);
|
||||||
|
this.panelGeneral.Name = "panelGeneral";
|
||||||
|
this.panelGeneral.Size = new System.Drawing.Size(322, 149);
|
||||||
|
this.panelGeneral.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// labelScrollSpeedValue
|
||||||
|
//
|
||||||
|
this.labelScrollSpeedValue.Location = new System.Drawing.Point(147, 53);
|
||||||
|
this.labelScrollSpeedValue.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||||
|
this.labelScrollSpeedValue.Name = "labelScrollSpeedValue";
|
||||||
|
this.labelScrollSpeedValue.Size = new System.Drawing.Size(34, 13);
|
||||||
|
this.labelScrollSpeedValue.TabIndex = 4;
|
||||||
|
this.labelScrollSpeedValue.Text = "100%";
|
||||||
|
this.labelScrollSpeedValue.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
//
|
||||||
|
// trackBarScrollSpeed
|
||||||
|
//
|
||||||
|
this.trackBarScrollSpeed.AutoSize = false;
|
||||||
|
this.trackBarScrollSpeed.LargeChange = 25;
|
||||||
|
this.trackBarScrollSpeed.Location = new System.Drawing.Point(5, 52);
|
||||||
|
this.trackBarScrollSpeed.Maximum = 200;
|
||||||
|
this.trackBarScrollSpeed.Minimum = 25;
|
||||||
|
this.trackBarScrollSpeed.Name = "trackBarScrollSpeed";
|
||||||
|
this.trackBarScrollSpeed.Size = new System.Drawing.Size(148, 30);
|
||||||
|
this.trackBarScrollSpeed.SmallChange = 5;
|
||||||
|
this.trackBarScrollSpeed.TabIndex = 3;
|
||||||
|
this.trackBarScrollSpeed.TickFrequency = 25;
|
||||||
|
this.trackBarScrollSpeed.Value = 100;
|
||||||
|
//
|
||||||
|
// labelScrollSpeed
|
||||||
|
//
|
||||||
|
this.labelScrollSpeed.AutoSize = true;
|
||||||
|
this.labelScrollSpeed.Location = new System.Drawing.Point(3, 36);
|
||||||
|
this.labelScrollSpeed.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelScrollSpeed.Name = "labelScrollSpeed";
|
||||||
|
this.labelScrollSpeed.Size = new System.Drawing.Size(67, 13);
|
||||||
|
this.labelScrollSpeed.TabIndex = 2;
|
||||||
|
this.labelScrollSpeed.Text = "Scroll Speed";
|
||||||
|
//
|
||||||
|
// labelLocation
|
||||||
|
//
|
||||||
|
this.labelLocation.AutoSize = true;
|
||||||
|
this.labelLocation.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelLocation.Location = new System.Drawing.Point(6, 395);
|
||||||
|
this.labelLocation.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelLocation.Name = "labelLocation";
|
||||||
|
this.labelLocation.Size = new System.Drawing.Size(70, 20);
|
||||||
|
this.labelLocation.TabIndex = 4;
|
||||||
|
this.labelLocation.Text = "Location";
|
||||||
|
//
|
||||||
|
// panelLocation
|
||||||
|
//
|
||||||
|
this.panelLocation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelLocation.Controls.Add(this.labelEdgeDistanceValue);
|
||||||
|
this.panelLocation.Controls.Add(this.radioLocTL);
|
||||||
|
this.panelLocation.Controls.Add(this.labelDisplay);
|
||||||
|
this.panelLocation.Controls.Add(this.trackBarEdgeDistance);
|
||||||
|
this.panelLocation.Controls.Add(this.comboBoxDisplay);
|
||||||
|
this.panelLocation.Controls.Add(this.radioLocTR);
|
||||||
|
this.panelLocation.Controls.Add(this.labelEdgeDistance);
|
||||||
|
this.panelLocation.Controls.Add(this.radioLocBL);
|
||||||
|
this.panelLocation.Controls.Add(this.radioLocCustom);
|
||||||
|
this.panelLocation.Controls.Add(this.radioLocBR);
|
||||||
|
this.panelLocation.Location = new System.Drawing.Point(9, 418);
|
||||||
|
this.panelLocation.Name = "panelLocation";
|
||||||
|
this.panelLocation.Size = new System.Drawing.Size(322, 165);
|
||||||
|
this.panelLocation.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// panelTimer
|
||||||
|
//
|
||||||
|
this.panelTimer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelTimer.Controls.Add(this.labelDuration);
|
||||||
|
this.panelTimer.Controls.Add(this.checkNotificationTimer);
|
||||||
|
this.panelTimer.Controls.Add(this.tableLayoutDurationButtons);
|
||||||
|
this.panelTimer.Controls.Add(this.checkTimerCountDown);
|
||||||
|
this.panelTimer.Controls.Add(this.labelDurationValue);
|
||||||
|
this.panelTimer.Controls.Add(this.trackBarDuration);
|
||||||
|
this.panelTimer.Location = new System.Drawing.Point(9, 227);
|
||||||
|
this.panelTimer.Name = "panelTimer";
|
||||||
|
this.panelTimer.Size = new System.Drawing.Size(322, 144);
|
||||||
|
this.panelTimer.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// labelDuration
|
||||||
|
//
|
||||||
|
this.labelDuration.AutoSize = true;
|
||||||
|
this.labelDuration.Location = new System.Drawing.Point(3, 60);
|
||||||
|
this.labelDuration.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
|
||||||
|
this.labelDuration.Name = "labelDuration";
|
||||||
|
this.labelDuration.Size = new System.Drawing.Size(47, 13);
|
||||||
|
this.labelDuration.TabIndex = 2;
|
||||||
|
this.labelDuration.Text = "Duration";
|
||||||
|
//
|
||||||
|
// labelTimer
|
||||||
|
//
|
||||||
|
this.labelTimer.AutoSize = true;
|
||||||
|
this.labelTimer.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelTimer.Location = new System.Drawing.Point(6, 204);
|
||||||
|
this.labelTimer.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelTimer.Name = "labelTimer";
|
||||||
|
this.labelTimer.Size = new System.Drawing.Size(48, 20);
|
||||||
|
this.labelTimer.TabIndex = 2;
|
||||||
|
this.labelTimer.Text = "Timer";
|
||||||
|
//
|
||||||
|
// labelSize
|
||||||
|
//
|
||||||
|
this.labelSize.AutoSize = true;
|
||||||
|
this.labelSize.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelSize.Location = new System.Drawing.Point(6, 607);
|
||||||
|
this.labelSize.Margin = new System.Windows.Forms.Padding(0, 21, 0, 0);
|
||||||
|
this.labelSize.Name = "labelSize";
|
||||||
|
this.labelSize.Size = new System.Drawing.Size(40, 20);
|
||||||
|
this.labelSize.TabIndex = 6;
|
||||||
|
this.labelSize.Text = "Size";
|
||||||
|
//
|
||||||
|
// panelMiscellaneous
|
||||||
|
//
|
||||||
|
this.panelMiscellaneous.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelMiscellaneous.Controls.Add(this.radioSizeCustom);
|
||||||
|
this.panelMiscellaneous.Controls.Add(this.radioSizeAuto);
|
||||||
|
this.panelMiscellaneous.Controls.Add(this.labelScrollSpeedValue);
|
||||||
|
this.panelMiscellaneous.Controls.Add(this.trackBarScrollSpeed);
|
||||||
|
this.panelMiscellaneous.Controls.Add(this.labelScrollSpeed);
|
||||||
|
this.panelMiscellaneous.Location = new System.Drawing.Point(9, 630);
|
||||||
|
this.panelMiscellaneous.Name = "panelMiscellaneous";
|
||||||
|
this.panelMiscellaneous.Size = new System.Drawing.Size(322, 92);
|
||||||
|
this.panelMiscellaneous.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// durationUpdateTimer
|
||||||
|
//
|
||||||
|
this.durationUpdateTimer.Interval = 200;
|
||||||
|
this.durationUpdateTimer.Tick += new System.EventHandler(this.durationUpdateTimer_Tick);
|
||||||
|
//
|
||||||
|
// checkMediaPreviews
|
||||||
|
//
|
||||||
|
this.checkMediaPreviews.AutoSize = true;
|
||||||
|
this.checkMediaPreviews.Location = new System.Drawing.Point(6, 28);
|
||||||
|
this.checkMediaPreviews.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
|
||||||
|
this.checkMediaPreviews.Name = "checkMediaPreviews";
|
||||||
|
this.checkMediaPreviews.Size = new System.Drawing.Size(131, 17);
|
||||||
|
this.checkMediaPreviews.TabIndex = 1;
|
||||||
|
this.checkMediaPreviews.Text = "Show Media Previews";
|
||||||
|
this.toolTip.SetToolTip(this.checkMediaPreviews, "Shows image and video thumbnails in the notification window.");
|
||||||
|
this.checkMediaPreviews.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// TabSettingsNotifications
|
// TabSettingsNotifications
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.Controls.Add(this.groupUserInterface);
|
this.Controls.Add(this.panelMiscellaneous);
|
||||||
this.Controls.Add(this.groupNotificationDuration);
|
this.Controls.Add(this.labelSize);
|
||||||
this.Controls.Add(this.groupNotificationLocation);
|
this.Controls.Add(this.labelTimer);
|
||||||
|
this.Controls.Add(this.panelLocation);
|
||||||
|
this.Controls.Add(this.labelLocation);
|
||||||
|
this.Controls.Add(this.panelGeneral);
|
||||||
|
this.Controls.Add(this.labelGeneral);
|
||||||
|
this.Controls.Add(this.panelTimer);
|
||||||
this.Name = "TabSettingsNotifications";
|
this.Name = "TabSettingsNotifications";
|
||||||
this.Size = new System.Drawing.Size(478, 282);
|
this.Size = new System.Drawing.Size(340, 731);
|
||||||
this.ParentChanged += new System.EventHandler(this.TabSettingsNotifications_ParentChanged);
|
this.ParentChanged += new System.EventHandler(this.TabSettingsNotifications_ParentChanged);
|
||||||
this.groupNotificationLocation.ResumeLayout(false);
|
|
||||||
this.groupNotificationLocation.PerformLayout();
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarEdgeDistance)).EndInit();
|
||||||
this.groupNotificationDuration.ResumeLayout(false);
|
|
||||||
this.groupNotificationDuration.PerformLayout();
|
|
||||||
this.tableLayoutDurationButtons.ResumeLayout(false);
|
this.tableLayoutDurationButtons.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.trackBarDuration)).EndInit();
|
||||||
this.groupUserInterface.ResumeLayout(false);
|
this.panelGeneral.ResumeLayout(false);
|
||||||
this.groupUserInterface.PerformLayout();
|
this.panelGeneral.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarScrollSpeed)).EndInit();
|
||||||
|
this.panelLocation.ResumeLayout(false);
|
||||||
|
this.panelLocation.PerformLayout();
|
||||||
|
this.panelTimer.ResumeLayout(false);
|
||||||
|
this.panelTimer.PerformLayout();
|
||||||
|
this.panelMiscellaneous.ResumeLayout(false);
|
||||||
|
this.panelMiscellaneous.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.GroupBox groupNotificationLocation;
|
|
||||||
private System.Windows.Forms.Label labelDisplay;
|
private System.Windows.Forms.Label labelDisplay;
|
||||||
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
private System.Windows.Forms.ComboBox comboBoxDisplay;
|
||||||
private System.Windows.Forms.Label labelEdgeDistance;
|
private System.Windows.Forms.Label labelEdgeDistance;
|
||||||
@@ -384,18 +585,36 @@
|
|||||||
private System.Windows.Forms.RadioButton radioLocBL;
|
private System.Windows.Forms.RadioButton radioLocBL;
|
||||||
private System.Windows.Forms.RadioButton radioLocTR;
|
private System.Windows.Forms.RadioButton radioLocTR;
|
||||||
private System.Windows.Forms.RadioButton radioLocTL;
|
private System.Windows.Forms.RadioButton radioLocTL;
|
||||||
private System.Windows.Forms.GroupBox groupNotificationDuration;
|
|
||||||
private System.Windows.Forms.GroupBox groupUserInterface;
|
|
||||||
private System.Windows.Forms.CheckBox checkNotificationTimer;
|
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
private System.Windows.Forms.Label labelEdgeDistanceValue;
|
private System.Windows.Forms.Label labelEdgeDistanceValue;
|
||||||
private System.Windows.Forms.CheckBox checkLegacyLoad;
|
|
||||||
private System.Windows.Forms.CheckBox checkTimerCountDown;
|
|
||||||
private System.Windows.Forms.Label labelDurationValue;
|
private System.Windows.Forms.Label labelDurationValue;
|
||||||
private System.Windows.Forms.TrackBar trackBarDuration;
|
private System.Windows.Forms.TrackBar trackBarDuration;
|
||||||
private System.Windows.Forms.TableLayoutPanel tableLayoutDurationButtons;
|
private System.Windows.Forms.TableLayoutPanel tableLayoutDurationButtons;
|
||||||
private TweetDck.Core.Controls.FlatButton btnDurationMedium;
|
private TweetDuck.Core.Controls.FlatButton btnDurationMedium;
|
||||||
private TweetDck.Core.Controls.FlatButton btnDurationLong;
|
private TweetDuck.Core.Controls.FlatButton btnDurationLong;
|
||||||
private TweetDck.Core.Controls.FlatButton btnDurationShort;
|
private TweetDuck.Core.Controls.FlatButton btnDurationShort;
|
||||||
|
private System.Windows.Forms.CheckBox checkNonIntrusive;
|
||||||
|
private System.Windows.Forms.Label labelIdlePause;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxIdlePause;
|
||||||
|
private System.Windows.Forms.CheckBox checkColumnName;
|
||||||
|
private System.Windows.Forms.CheckBox checkSkipOnLinkClick;
|
||||||
|
private System.Windows.Forms.CheckBox checkTimerCountDown;
|
||||||
|
private System.Windows.Forms.CheckBox checkNotificationTimer;
|
||||||
|
private System.Windows.Forms.Label labelGeneral;
|
||||||
|
private System.Windows.Forms.Panel panelGeneral;
|
||||||
|
private System.Windows.Forms.Label labelLocation;
|
||||||
|
private System.Windows.Forms.Panel panelLocation;
|
||||||
|
private System.Windows.Forms.Panel panelTimer;
|
||||||
|
private System.Windows.Forms.Label labelTimer;
|
||||||
|
private System.Windows.Forms.Label labelScrollSpeedValue;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarScrollSpeed;
|
||||||
|
private System.Windows.Forms.Label labelScrollSpeed;
|
||||||
|
private System.Windows.Forms.Label labelSize;
|
||||||
|
private System.Windows.Forms.Panel panelMiscellaneous;
|
||||||
|
private System.Windows.Forms.Label labelDuration;
|
||||||
|
private System.Windows.Forms.Timer durationUpdateTimer;
|
||||||
|
private System.Windows.Forms.RadioButton radioSizeCustom;
|
||||||
|
private System.Windows.Forms.RadioButton radioSizeAuto;
|
||||||
|
private System.Windows.Forms.CheckBox checkMediaPreviews;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,29 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TweetDck.Core.Handling;
|
using TweetDuck.Core.Controls;
|
||||||
using TweetDck.Core.Controls;
|
using TweetDuck.Core.Notification;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings{
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
partial class TabSettingsNotifications : BaseTabSettings{
|
partial class TabSettingsNotifications : BaseTabSettings{
|
||||||
private readonly FormNotification notification;
|
private static readonly int[] IdlePauseSeconds = { 0, 30, 60, 120, 300 };
|
||||||
|
|
||||||
public TabSettingsNotifications(FormNotification notification){
|
private readonly FormNotificationMain notification;
|
||||||
|
|
||||||
|
public TabSettingsNotifications(FormNotificationMain notification){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
this.notification.CanMoveWindow = () => radioLocCustom.Checked;
|
|
||||||
|
|
||||||
this.notification.Move += (sender, args) => {
|
|
||||||
if (radioLocCustom.Checked){
|
|
||||||
Config.CustomNotificationPosition = this.notification.Location;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.notification.Initialized += (sender, args) => {
|
this.notification.Initialized += (sender, args) => {
|
||||||
this.InvokeSafe(() => this.notification.ShowNotificationForSettings(true));
|
this.InvokeAsyncSafe(() => {
|
||||||
|
this.notification.ShowNotificationForSettings(true);
|
||||||
|
this.notification.Move += notification_Move;
|
||||||
|
this.notification.ResizeEnd += notification_ResizeEnd;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.notification.Show(this);
|
this.notification.Activated += notification_Activated;
|
||||||
|
this.notification.Show();
|
||||||
|
|
||||||
switch(Config.NotificationPosition){
|
switch(Config.NotificationPosition){
|
||||||
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
case TweetNotification.Position.TopLeft: radioLocTL.Checked = true; break;
|
||||||
@@ -34,28 +33,81 @@ namespace TweetDck.Core.Other.Settings{
|
|||||||
case TweetNotification.Position.Custom: radioLocCustom.Checked = true; break;
|
case TweetNotification.Position.Custom: radioLocCustom.Checked = true; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
||||||
|
|
||||||
|
switch(Config.NotificationSize){
|
||||||
|
case TweetNotification.Size.Auto: radioSizeAuto.Checked = true; break;
|
||||||
|
case TweetNotification.Size.Custom: radioSizeCustom.Checked = true; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
toolTip.SetToolTip(trackBarDuration, toolTip.GetToolTip(labelDurationValue));
|
||||||
trackBarDuration.SetValueSafe(Config.NotificationDurationValue);
|
trackBarDuration.SetValueSafe(Config.NotificationDurationValue);
|
||||||
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
||||||
|
|
||||||
comboBoxDisplay.Items.Add("(Same As "+Program.BrandName+")");
|
comboBoxIdlePause.Items.Add("Disabled");
|
||||||
|
comboBoxIdlePause.Items.Add("30 seconds");
|
||||||
|
comboBoxIdlePause.Items.Add("1 minute");
|
||||||
|
comboBoxIdlePause.Items.Add("2 minutes");
|
||||||
|
comboBoxIdlePause.Items.Add("5 minutes");
|
||||||
|
comboBoxIdlePause.SelectedIndex = Math.Max(0, Array.FindIndex(IdlePauseSeconds, val => val == Config.NotificationIdlePauseSeconds));
|
||||||
|
|
||||||
|
comboBoxDisplay.Items.Add("(Same as TweetDuck)");
|
||||||
|
|
||||||
foreach(Screen screen in Screen.AllScreens){
|
foreach(Screen screen in Screen.AllScreens){
|
||||||
comboBoxDisplay.Items.Add(screen.DeviceName+" ("+screen.Bounds.Width+"x"+screen.Bounds.Height+")");
|
comboBoxDisplay.Items.Add(screen.DeviceName.TrimStart('\\', '.')+" ("+screen.Bounds.Width+"x"+screen.Bounds.Height+")");
|
||||||
}
|
}
|
||||||
|
|
||||||
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1, Config.NotificationDisplay);
|
comboBoxDisplay.SelectedIndex = Math.Min(comboBoxDisplay.Items.Count-1, Config.NotificationDisplay);
|
||||||
|
|
||||||
|
checkColumnName.Checked = Config.DisplayNotificationColumn;
|
||||||
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
|
checkNotificationTimer.Checked = Config.DisplayNotificationTimer;
|
||||||
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
||||||
checkTimerCountDown.Checked = Config.NotificationTimerCountDown;
|
checkTimerCountDown.Checked = Config.NotificationTimerCountDown;
|
||||||
checkLegacyLoad.Checked = Config.NotificationLegacyLoad;
|
checkMediaPreviews.Checked = Config.NotificationMediaPreviews;
|
||||||
|
checkSkipOnLinkClick.Checked = Config.NotificationSkipOnLinkClick;
|
||||||
|
checkNonIntrusive.Checked = Config.NotificationNonIntrusiveMode;
|
||||||
|
|
||||||
|
trackBarScrollSpeed.SetValueSafe(Config.NotificationScrollSpeed);
|
||||||
|
labelScrollSpeedValue.Text = trackBarScrollSpeed.Value+"%";
|
||||||
|
|
||||||
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
|
trackBarEdgeDistance.SetValueSafe(Config.NotificationEdgeDistance);
|
||||||
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value.ToString(CultureInfo.InvariantCulture)+" px";
|
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value+" px";
|
||||||
|
|
||||||
|
this.notification.CanMoveWindow = () => radioLocCustom.Checked;
|
||||||
|
this.notification.CanResizeWindow = radioSizeCustom.Checked;
|
||||||
|
|
||||||
Disposed += (sender, args) => this.notification.Dispose();
|
Disposed += (sender, args) => this.notification.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
radioLocTL.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocTR.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocBL.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocBR.CheckedChanged += radioLoc_CheckedChanged;
|
||||||
|
radioLocCustom.Click += radioLocCustom_Click;
|
||||||
|
|
||||||
|
radioSizeAuto.CheckedChanged += radioSize_CheckedChanged;
|
||||||
|
radioSizeCustom.Click += radioSizeCustom_Click;
|
||||||
|
|
||||||
|
trackBarDuration.ValueChanged += trackBarDuration_ValueChanged;
|
||||||
|
btnDurationShort.Click += btnDurationShort_Click;
|
||||||
|
btnDurationMedium.Click += btnDurationMedium_Click;
|
||||||
|
btnDurationLong.Click += btnDurationLong_Click;
|
||||||
|
|
||||||
|
checkColumnName.CheckedChanged += checkColumnName_CheckedChanged;
|
||||||
|
checkNotificationTimer.CheckedChanged += checkNotificationTimer_CheckedChanged;
|
||||||
|
checkTimerCountDown.CheckedChanged += checkTimerCountDown_CheckedChanged;
|
||||||
|
checkMediaPreviews.CheckedChanged += checkMediaPreviews_CheckedChanged;
|
||||||
|
checkSkipOnLinkClick.CheckedChanged += checkSkipOnLinkClick_CheckedChanged;
|
||||||
|
checkNonIntrusive.CheckedChanged += checkNonIntrusive_CheckedChanged;
|
||||||
|
|
||||||
|
comboBoxIdlePause.SelectedValueChanged += comboBoxIdlePause_SelectedValueChanged;
|
||||||
|
trackBarScrollSpeed.ValueChanged += trackBarScrollSpeed_ValueChanged;
|
||||||
|
|
||||||
|
comboBoxDisplay.SelectedValueChanged += comboBoxDisplay_SelectedValueChanged;
|
||||||
|
trackBarEdgeDistance.ValueChanged += trackBarEdgeDistance_ValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
private void TabSettingsNotifications_ParentChanged(object sender, EventArgs e){
|
private void TabSettingsNotifications_ParentChanged(object sender, EventArgs e){
|
||||||
if (Parent == null){
|
if (Parent == null){
|
||||||
notification.HideNotification(false);
|
notification.HideNotification(false);
|
||||||
@@ -65,86 +117,146 @@ namespace TweetDck.Core.Other.Settings{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void radioLoc_CheckedChanged(object sender, EventArgs e){
|
private void notification_Activated(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
notification.Hide();
|
||||||
|
notification.Activated -= notification_Activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notification_Move(object sender, EventArgs e){
|
||||||
|
if (radioLocCustom.Checked && notification.Location != ControlExtensions.InvisibleLocation){
|
||||||
|
Config.CustomNotificationPosition = notification.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notification_ResizeEnd(object sender, EventArgs e){
|
||||||
|
if (radioSizeCustom.Checked){
|
||||||
|
Config.CustomNotificationSize = notification.BrowserSize;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioLoc_CheckedChanged(object sender, EventArgs e){
|
||||||
if (radioLocTL.Checked)Config.NotificationPosition = TweetNotification.Position.TopLeft;
|
if (radioLocTL.Checked)Config.NotificationPosition = TweetNotification.Position.TopLeft;
|
||||||
else if (radioLocTR.Checked)Config.NotificationPosition = TweetNotification.Position.TopRight;
|
else if (radioLocTR.Checked)Config.NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
else if (radioLocBL.Checked)Config.NotificationPosition = TweetNotification.Position.BottomLeft;
|
else if (radioLocBL.Checked)Config.NotificationPosition = TweetNotification.Position.BottomLeft;
|
||||||
else if (radioLocBR.Checked)Config.NotificationPosition = TweetNotification.Position.BottomRight;
|
else if (radioLocBR.Checked)Config.NotificationPosition = TweetNotification.Position.BottomRight;
|
||||||
else if (radioLocCustom.Checked){
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = true;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioLocCustom_Click(object sender, EventArgs e){
|
||||||
if (!Config.IsCustomNotificationPositionSet){
|
if (!Config.IsCustomNotificationPositionSet){
|
||||||
Config.CustomNotificationPosition = notification.Location;
|
Config.CustomNotificationPosition = notification.Location;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.NotificationPosition = TweetNotification.Position.Custom;
|
Config.NotificationPosition = TweetNotification.Position.Custom;
|
||||||
|
|
||||||
|
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = false;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
|
||||||
|
if (notification.IsFullyOutsideView() && FormMessage.Question("Notification is outside view", "The notification seems to be outside of view, would you like to reset its position?", FormMessage.Yes, FormMessage.No)){
|
||||||
|
Config.NotificationPosition = TweetNotification.Position.TopRight;
|
||||||
|
notification.MoveToVisibleLocation();
|
||||||
|
|
||||||
|
Config.CustomNotificationPosition = notification.Location;
|
||||||
|
|
||||||
|
Config.NotificationPosition = TweetNotification.Position.Custom;
|
||||||
|
notification.MoveToVisibleLocation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comboBoxDisplay.Enabled = trackBarEdgeDistance.Enabled = !radioLocCustom.Checked;
|
private void radioSize_CheckedChanged(object sender, EventArgs e){
|
||||||
|
if (radioSizeAuto.Checked)Config.NotificationSize = TweetNotification.Size.Auto;
|
||||||
|
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
notification.CanResizeWindow = false; // must be after ShowNotificationForSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioSizeCustom_Click(object sender, EventArgs e){
|
||||||
|
if (!Config.IsCustomNotificationSizeSet){
|
||||||
|
Config.CustomNotificationSize = notification.BrowserSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.NotificationSize = TweetNotification.Size.Custom;
|
||||||
|
|
||||||
|
notification.CanResizeWindow = true;
|
||||||
notification.ShowNotificationForSettings(false);
|
notification.ShowNotificationForSettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trackBarDuration_ValueChanged(object sender, EventArgs e){
|
private void trackBarDuration_ValueChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
durationUpdateTimer.Stop();
|
||||||
|
durationUpdateTimer.Start();
|
||||||
|
|
||||||
Config.NotificationDurationValue = trackBarDuration.Value;
|
Config.NotificationDurationValue = trackBarDuration.Value;
|
||||||
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
labelDurationValue.Text = Config.NotificationDurationValue+" ms/c";
|
||||||
|
|
||||||
notification.ShowNotificationForSettings(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnDurationShort_Click(object sender, EventArgs e){
|
private void btnDurationShort_Click(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
trackBarDuration.Value = 15;
|
trackBarDuration.Value = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnDurationMedium_Click(object sender, EventArgs e){
|
private void btnDurationMedium_Click(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
trackBarDuration.Value = 25;
|
trackBarDuration.Value = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnDurationLong_Click(object sender, EventArgs e){
|
private void btnDurationLong_Click(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
trackBarDuration.Value = 35;
|
trackBarDuration.Value = 35;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){
|
private void checkColumnName_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
Config.DisplayNotificationColumn = checkColumnName.Checked;
|
||||||
|
notification.ShowNotificationForSettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNotificationTimer_CheckedChanged(object sender, EventArgs e){
|
||||||
Config.DisplayNotificationTimer = checkNotificationTimer.Checked;
|
Config.DisplayNotificationTimer = checkNotificationTimer.Checked;
|
||||||
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
checkTimerCountDown.Enabled = checkNotificationTimer.Checked;
|
||||||
notification.ShowNotificationForSettings(true);
|
notification.ShowNotificationForSettings(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTimerCountDown_CheckedChanged(object sender, EventArgs e){
|
private void checkTimerCountDown_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.NotificationTimerCountDown = checkTimerCountDown.Checked;
|
Config.NotificationTimerCountDown = checkTimerCountDown.Checked;
|
||||||
notification.ShowNotificationForSettings(true);
|
notification.ShowNotificationForSettings(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkLegacyLoad_CheckedChanged(object sender, EventArgs e){
|
private void checkMediaPreviews_CheckedChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
Config.NotificationMediaPreviews = checkMediaPreviews.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
Config.NotificationLegacyLoad = checkLegacyLoad.Checked;
|
private void checkSkipOnLinkClick_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationSkipOnLinkClick = checkSkipOnLinkClick.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNonIntrusive_CheckedChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationNonIntrusiveMode = checkNonIntrusive.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxIdlePause_SelectedValueChanged(object sender, EventArgs e){
|
||||||
|
Config.NotificationIdlePauseSeconds = IdlePauseSeconds[comboBoxIdlePause.SelectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trackBarScrollSpeed_ValueChanged(object sender, EventArgs e){
|
||||||
|
if (trackBarScrollSpeed.AlignValueToTick()){
|
||||||
|
labelScrollSpeedValue.Text = trackBarScrollSpeed.Value+"%";
|
||||||
|
Config.NotificationScrollSpeed = trackBarScrollSpeed.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void comboBoxDisplay_SelectedValueChanged(object sender, EventArgs e){
|
private void comboBoxDisplay_SelectedValueChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.NotificationDisplay = comboBoxDisplay.SelectedIndex;
|
Config.NotificationDisplay = comboBoxDisplay.SelectedIndex;
|
||||||
notification.ShowNotificationForSettings(false);
|
notification.ShowNotificationForSettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trackBarEdgeDistance_ValueChanged(object sender, EventArgs e){
|
private void trackBarEdgeDistance_ValueChanged(object sender, EventArgs e){
|
||||||
if (!Ready)return;
|
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value+" px";
|
||||||
|
|
||||||
labelEdgeDistanceValue.Text = trackBarEdgeDistance.Value.ToString(CultureInfo.InvariantCulture)+" px";
|
|
||||||
Config.NotificationEdgeDistance = trackBarEdgeDistance.Value;
|
Config.NotificationEdgeDistance = trackBarEdgeDistance.Value;
|
||||||
notification.ShowNotificationForSettings(false);
|
notification.ShowNotificationForSettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void durationUpdateTimer_Tick(object sender, EventArgs e){
|
||||||
|
notification.ShowNotificationForSettings(true);
|
||||||
|
durationUpdateTimer.Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
131
Core/Other/Settings/TabSettingsSounds.Designer.cs
generated
Normal file
131
Core/Other/Settings/TabSettingsSounds.Designer.cs
generated
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
namespace TweetDuck.Core.Other.Settings {
|
||||||
|
partial class TabSettingsSounds {
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing && (components != null)) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
|
this.btnPlaySound = new System.Windows.Forms.Button();
|
||||||
|
this.btnResetSound = new System.Windows.Forms.Button();
|
||||||
|
this.btnBrowseSound = new System.Windows.Forms.Button();
|
||||||
|
this.tbCustomSound = new System.Windows.Forms.TextBox();
|
||||||
|
this.labelSoundNotification = new System.Windows.Forms.Label();
|
||||||
|
this.panelSoundNotification = new System.Windows.Forms.Panel();
|
||||||
|
this.panelSoundNotification.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnPlaySound
|
||||||
|
//
|
||||||
|
this.btnPlaySound.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnPlaySound.AutoSize = true;
|
||||||
|
this.btnPlaySound.Location = new System.Drawing.Point(203, 29);
|
||||||
|
this.btnPlaySound.Name = "btnPlaySound";
|
||||||
|
this.btnPlaySound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnPlaySound.Size = new System.Drawing.Size(43, 23);
|
||||||
|
this.btnPlaySound.TabIndex = 2;
|
||||||
|
this.btnPlaySound.Text = "Play";
|
||||||
|
this.btnPlaySound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnResetSound
|
||||||
|
//
|
||||||
|
this.btnResetSound.AutoSize = true;
|
||||||
|
this.btnResetSound.Location = new System.Drawing.Point(3, 29);
|
||||||
|
this.btnResetSound.Name = "btnResetSound";
|
||||||
|
this.btnResetSound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnResetSound.Size = new System.Drawing.Size(51, 23);
|
||||||
|
this.btnResetSound.TabIndex = 3;
|
||||||
|
this.btnResetSound.Text = "Reset";
|
||||||
|
this.btnResetSound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// btnBrowseSound
|
||||||
|
//
|
||||||
|
this.btnBrowseSound.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.btnBrowseSound.AutoSize = true;
|
||||||
|
this.btnBrowseSound.Location = new System.Drawing.Point(252, 29);
|
||||||
|
this.btnBrowseSound.Name = "btnBrowseSound";
|
||||||
|
this.btnBrowseSound.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
|
||||||
|
this.btnBrowseSound.Size = new System.Drawing.Size(67, 23);
|
||||||
|
this.btnBrowseSound.TabIndex = 1;
|
||||||
|
this.btnBrowseSound.Text = "Browse...";
|
||||||
|
this.btnBrowseSound.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tbCustomSound
|
||||||
|
//
|
||||||
|
this.tbCustomSound.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.tbCustomSound.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.tbCustomSound.Name = "tbCustomSound";
|
||||||
|
this.tbCustomSound.Size = new System.Drawing.Size(316, 20);
|
||||||
|
this.tbCustomSound.TabIndex = 0;
|
||||||
|
this.toolTip.SetToolTip(this.tbCustomSound, "When empty, the default TweetDeck sound notification is used.");
|
||||||
|
//
|
||||||
|
// labelSoundNotification
|
||||||
|
//
|
||||||
|
this.labelSoundNotification.AutoSize = true;
|
||||||
|
this.labelSoundNotification.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
|
this.labelSoundNotification.Location = new System.Drawing.Point(6, 8);
|
||||||
|
this.labelSoundNotification.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0);
|
||||||
|
this.labelSoundNotification.Name = "labelSoundNotification";
|
||||||
|
this.labelSoundNotification.Size = new System.Drawing.Size(198, 20);
|
||||||
|
this.labelSoundNotification.TabIndex = 1;
|
||||||
|
this.labelSoundNotification.Text = "Custom Sound Notification";
|
||||||
|
//
|
||||||
|
// panelSoundNotification
|
||||||
|
//
|
||||||
|
this.panelSoundNotification.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.panelSoundNotification.Controls.Add(this.btnPlaySound);
|
||||||
|
this.panelSoundNotification.Controls.Add(this.tbCustomSound);
|
||||||
|
this.panelSoundNotification.Controls.Add(this.btnResetSound);
|
||||||
|
this.panelSoundNotification.Controls.Add(this.btnBrowseSound);
|
||||||
|
this.panelSoundNotification.Location = new System.Drawing.Point(9, 31);
|
||||||
|
this.panelSoundNotification.Name = "panelSoundNotification";
|
||||||
|
this.panelSoundNotification.Size = new System.Drawing.Size(322, 56);
|
||||||
|
this.panelSoundNotification.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// TabSettingsSounds
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.panelSoundNotification);
|
||||||
|
this.Controls.Add(this.labelSoundNotification);
|
||||||
|
this.Name = "TabSettingsSounds";
|
||||||
|
this.Size = new System.Drawing.Size(340, 97);
|
||||||
|
this.panelSoundNotification.ResumeLayout(false);
|
||||||
|
this.panelSoundNotification.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ToolTip toolTip;
|
||||||
|
private System.Windows.Forms.Button btnResetSound;
|
||||||
|
private System.Windows.Forms.Button btnBrowseSound;
|
||||||
|
private System.Windows.Forms.TextBox tbCustomSound;
|
||||||
|
private System.Windows.Forms.Button btnPlaySound;
|
||||||
|
private System.Windows.Forms.Label labelSoundNotification;
|
||||||
|
private System.Windows.Forms.Panel panelSoundNotification;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
Core/Other/Settings/TabSettingsSounds.cs
Normal file
67
Core/Other/Settings/TabSettingsSounds.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Notification;
|
||||||
|
using TweetLib.Audio;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Other.Settings{
|
||||||
|
partial class TabSettingsSounds : BaseTabSettings{
|
||||||
|
private readonly SoundNotification soundNotification;
|
||||||
|
|
||||||
|
public TabSettingsSounds(){
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
soundNotification = new SoundNotification();
|
||||||
|
soundNotification.PlaybackError += sound_PlaybackError;
|
||||||
|
|
||||||
|
tbCustomSound.Text = Config.NotificationSoundPath;
|
||||||
|
tbCustomSound_TextChanged(tbCustomSound, new EventArgs());
|
||||||
|
|
||||||
|
Disposed += (sender, args) => soundNotification.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnReady(){
|
||||||
|
tbCustomSound.TextChanged += tbCustomSound_TextChanged;
|
||||||
|
btnPlaySound.Click += btnPlaySound_Click;
|
||||||
|
btnBrowseSound.Click += btnBrowseSound_Click;
|
||||||
|
btnResetSound.Click += btnResetSound_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClosing(){
|
||||||
|
Config.NotificationSoundPath = tbCustomSound.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tbCustomSound_TextChanged(object sender, EventArgs e){
|
||||||
|
bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
|
||||||
|
tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Red;
|
||||||
|
btnPlaySound.Enabled = !isEmpty;
|
||||||
|
btnResetSound.Enabled = !isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnPlaySound_Click(object sender, EventArgs e){
|
||||||
|
soundNotification.Play(tbCustomSound.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){
|
||||||
|
FormMessage.Error("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, FormMessage.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnBrowseSound_Click(object sender, EventArgs e){
|
||||||
|
using(OpenFileDialog dialog = new OpenFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
DereferenceLinks = true,
|
||||||
|
Title = "Custom Notification Sound",
|
||||||
|
Filter = "Sound file ("+soundNotification.SupportedFormats+")|"+soundNotification.SupportedFormats+"|All files (*.*)|*.*"
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
tbCustomSound.Text = dialog.FileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnResetSound_Click(object sender, EventArgs e){
|
||||||
|
tbCustomSound.Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
Core/Other/Settings/TabSettingsUpdates.Designer.cs
generated
90
Core/Other/Settings/TabSettingsUpdates.Designer.cs
generated
@@ -1,90 +0,0 @@
|
|||||||
namespace TweetDck.Core.Other.Settings {
|
|
||||||
partial class TabSettingsUpdates {
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing) {
|
|
||||||
if (disposing && (components != null)) {
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Component Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent() {
|
|
||||||
this.components = new System.ComponentModel.Container();
|
|
||||||
this.btnCheckUpdates = new System.Windows.Forms.Button();
|
|
||||||
this.checkUpdateNotifications = new System.Windows.Forms.CheckBox();
|
|
||||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
|
||||||
this.groupGeneral = new System.Windows.Forms.GroupBox();
|
|
||||||
this.groupGeneral.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// btnCheckUpdates
|
|
||||||
//
|
|
||||||
this.btnCheckUpdates.Location = new System.Drawing.Point(6, 44);
|
|
||||||
this.btnCheckUpdates.Name = "btnCheckUpdates";
|
|
||||||
this.btnCheckUpdates.Size = new System.Drawing.Size(171, 23);
|
|
||||||
this.btnCheckUpdates.TabIndex = 15;
|
|
||||||
this.btnCheckUpdates.Text = "Check Updates Now";
|
|
||||||
this.toolTip.SetToolTip(this.btnCheckUpdates, "Forces an update check, even for updates that had been dismissed.");
|
|
||||||
this.btnCheckUpdates.UseVisualStyleBackColor = true;
|
|
||||||
this.btnCheckUpdates.Click += new System.EventHandler(this.btnCheckUpdates_Click);
|
|
||||||
//
|
|
||||||
// checkUpdateNotifications
|
|
||||||
//
|
|
||||||
this.checkUpdateNotifications.AutoSize = true;
|
|
||||||
this.checkUpdateNotifications.Location = new System.Drawing.Point(6, 21);
|
|
||||||
this.checkUpdateNotifications.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
|
|
||||||
this.checkUpdateNotifications.Name = "checkUpdateNotifications";
|
|
||||||
this.checkUpdateNotifications.Size = new System.Drawing.Size(165, 17);
|
|
||||||
this.checkUpdateNotifications.TabIndex = 14;
|
|
||||||
this.checkUpdateNotifications.Text = "Check Updates Automatically";
|
|
||||||
this.toolTip.SetToolTip(this.checkUpdateNotifications, "Checks for updates every hour.\r\nIf an update is dismissed, it will not appear aga" +
|
|
||||||
"in.");
|
|
||||||
this.checkUpdateNotifications.UseVisualStyleBackColor = true;
|
|
||||||
this.checkUpdateNotifications.CheckedChanged += new System.EventHandler(this.checkUpdateNotifications_CheckedChanged);
|
|
||||||
//
|
|
||||||
// groupGeneral
|
|
||||||
//
|
|
||||||
this.groupGeneral.Controls.Add(this.checkUpdateNotifications);
|
|
||||||
this.groupGeneral.Controls.Add(this.btnCheckUpdates);
|
|
||||||
this.groupGeneral.Location = new System.Drawing.Point(9, 9);
|
|
||||||
this.groupGeneral.Name = "groupGeneral";
|
|
||||||
this.groupGeneral.Size = new System.Drawing.Size(183, 75);
|
|
||||||
this.groupGeneral.TabIndex = 16;
|
|
||||||
this.groupGeneral.TabStop = false;
|
|
||||||
this.groupGeneral.Text = "General";
|
|
||||||
//
|
|
||||||
// TabSettingsUpdates
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.Controls.Add(this.groupGeneral);
|
|
||||||
this.Name = "TabSettingsUpdates";
|
|
||||||
this.Size = new System.Drawing.Size(478, 282);
|
|
||||||
this.groupGeneral.ResumeLayout(false);
|
|
||||||
this.groupGeneral.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.Button btnCheckUpdates;
|
|
||||||
private System.Windows.Forms.CheckBox checkUpdateNotifications;
|
|
||||||
private System.Windows.Forms.ToolTip toolTip;
|
|
||||||
private System.Windows.Forms.GroupBox groupGeneral;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using TweetDck.Updates;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings{
|
|
||||||
partial class TabSettingsUpdates : BaseTabSettings{
|
|
||||||
private readonly UpdateHandler updates;
|
|
||||||
private int updateCheckEventId = -1;
|
|
||||||
|
|
||||||
public TabSettingsUpdates(UpdateHandler updates){
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
this.updates = updates;
|
|
||||||
|
|
||||||
this.updates.CheckFinished += updates_CheckFinished;
|
|
||||||
Disposed += (sender, args) => this.updates.CheckFinished -= updates_CheckFinished;
|
|
||||||
|
|
||||||
checkUpdateNotifications.Checked = Config.EnableUpdateCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkUpdateNotifications_CheckedChanged(object sender, EventArgs e){
|
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.EnableUpdateCheck = checkUpdateNotifications.Checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnCheckUpdates_Click(object sender, EventArgs e){
|
|
||||||
if (!Ready)return;
|
|
||||||
|
|
||||||
Config.DismissedUpdate = string.Empty;
|
|
||||||
Config.Save();
|
|
||||||
|
|
||||||
updateCheckEventId = updates.Check(true);
|
|
||||||
|
|
||||||
btnCheckUpdates.Enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
|
||||||
if (e.EventId == updateCheckEventId){
|
|
||||||
btnCheckUpdates.Enabled = true;
|
|
||||||
|
|
||||||
if (!e.UpdateAvailable){
|
|
||||||
MessageBox.Show("Your version of "+Program.BrandName+" is up to date.", "No Updates Available", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
50
Core/TrayIcon.Designer.cs
generated
50
Core/TrayIcon.Designer.cs
generated
@@ -1,4 +1,4 @@
|
|||||||
namespace TweetDck.Core {
|
namespace TweetDuck.Core {
|
||||||
partial class TrayIcon {
|
partial class TrayIcon {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@@ -25,65 +25,17 @@
|
|||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||||
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
|
||||||
this.restoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.muteNotificationsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.closeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.contextMenu.SuspendLayout();
|
|
||||||
//
|
//
|
||||||
// notifyIcon
|
// notifyIcon
|
||||||
//
|
//
|
||||||
this.notifyIcon.ContextMenuStrip = this.contextMenu;
|
|
||||||
this.notifyIcon.Icon = global::TweetDck.Properties.Resources.icon_tray;
|
|
||||||
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.trayIcon_MouseClick);
|
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.trayIcon_MouseClick);
|
||||||
//
|
//
|
||||||
// contextMenu
|
|
||||||
//
|
|
||||||
this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.restoreToolStripMenuItem,
|
|
||||||
this.muteNotificationsToolStripMenuItem,
|
|
||||||
this.closeToolStripMenuItem});
|
|
||||||
this.contextMenu.Name = "contextMenuTray";
|
|
||||||
this.contextMenu.ShowCheckMargin = true;
|
|
||||||
this.contextMenu.ShowImageMargin = false;
|
|
||||||
this.contextMenu.ShowItemToolTips = false;
|
|
||||||
this.contextMenu.Size = new System.Drawing.Size(174, 92);
|
|
||||||
this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuTray_Opening);
|
|
||||||
this.contextMenu.Opened += new System.EventHandler(this.contextMenuTray_Opened);
|
|
||||||
//
|
|
||||||
// restoreToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.restoreToolStripMenuItem.Name = "restoreToolStripMenuItem";
|
|
||||||
this.restoreToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.restoreToolStripMenuItem.Text = "Restore";
|
|
||||||
this.restoreToolStripMenuItem.Click += new System.EventHandler(this.restoreToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// muteNotificationsToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.muteNotificationsToolStripMenuItem.CheckOnClick = true;
|
|
||||||
this.muteNotificationsToolStripMenuItem.Name = "muteNotificationsToolStripMenuItem";
|
|
||||||
this.muteNotificationsToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.muteNotificationsToolStripMenuItem.Text = "Mute Notifications";
|
|
||||||
this.muteNotificationsToolStripMenuItem.CheckedChanged += new System.EventHandler(this.muteNotificationsToolStripMenuItem_CheckedChanged);
|
|
||||||
//
|
|
||||||
// closeToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
|
|
||||||
this.closeToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
|
|
||||||
this.closeToolStripMenuItem.Text = "Close";
|
|
||||||
this.closeToolStripMenuItem.Click += new System.EventHandler(this.closeToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// TrayIcon
|
// TrayIcon
|
||||||
//
|
//
|
||||||
this.contextMenu.ResumeLayout(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.NotifyIcon notifyIcon;
|
private System.Windows.Forms.NotifyIcon notifyIcon;
|
||||||
private System.Windows.Forms.ContextMenuStrip contextMenu;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem restoreToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem muteNotificationsToolStripMenuItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core{
|
namespace TweetDuck.Core{
|
||||||
partial class TrayIcon : Component{
|
partial class TrayIcon : Component{
|
||||||
public enum Behavior{ // keep order
|
public enum Behavior{ // keep order
|
||||||
Disabled, DisplayOnly, MinimizeToTray, CloseToTray, Combined
|
Disabled, DisplayOnly, MinimizeToTray, CloseToTray, Combined
|
||||||
@@ -12,12 +12,15 @@ namespace TweetDck.Core{
|
|||||||
public event EventHandler ClickClose;
|
public event EventHandler ClickClose;
|
||||||
|
|
||||||
public bool Visible{
|
public bool Visible{
|
||||||
get{
|
get => notifyIcon.Visible;
|
||||||
return notifyIcon.Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
set{
|
set{
|
||||||
|
if (value){
|
||||||
|
notifyIcon.Icon = Properties.Resources.icon_tray;
|
||||||
|
}
|
||||||
|
|
||||||
notifyIcon.Visible = value;
|
notifyIcon.Visible = value;
|
||||||
|
hasNotifications = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,52 +30,56 @@ namespace TweetDck.Core{
|
|||||||
}
|
}
|
||||||
|
|
||||||
set{
|
set{
|
||||||
if (hasNotifications != value){
|
if (hasNotifications != value && Visible){
|
||||||
notifyIcon.Icon = value ? Properties.Resources.icon_tray_new : Properties.Resources.icon_tray;
|
notifyIcon.Icon = value ? Properties.Resources.icon_tray_new : Properties.Resources.icon_tray;
|
||||||
hasNotifications = value;
|
hasNotifications = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly ContextMenu contextMenu;
|
||||||
private bool hasNotifications;
|
private bool hasNotifications;
|
||||||
|
|
||||||
public TrayIcon(){
|
public TrayIcon(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
notifyIcon.Text = Program.BrandName;
|
|
||||||
|
this.contextMenu = new ContextMenu();
|
||||||
|
this.contextMenu.MenuItems.Add("Restore", menuItemRestore_Click);
|
||||||
|
this.contextMenu.MenuItems.Add("Mute notifications", menuItemMuteNotifications_Click);
|
||||||
|
this.contextMenu.MenuItems.Add("Close", menuItemClose_Click);
|
||||||
|
this.contextMenu.Popup += contextMenu_Popup;
|
||||||
|
|
||||||
|
this.notifyIcon.ContextMenu = contextMenu;
|
||||||
|
this.notifyIcon.Text = Program.BrandName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrayIcon(IContainer container) : this(){
|
||||||
|
container.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
|
|
||||||
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
private void trayIcon_MouseClick(object sender, MouseEventArgs e){
|
||||||
if (e.Button == MouseButtons.Left){
|
if (e.Button == MouseButtons.Left){
|
||||||
restoreToolStripMenuItem_Click(sender, e);
|
menuItemRestore_Click(sender, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contextMenuTray_Opening(object sender, CancelEventArgs e){
|
private void contextMenu_Popup(object sender, EventArgs e){
|
||||||
muteNotificationsToolStripMenuItem.CheckedChanged -= muteNotificationsToolStripMenuItem_CheckedChanged;
|
contextMenu.MenuItems[1].Checked = Program.UserConfig.MuteNotifications;
|
||||||
muteNotificationsToolStripMenuItem.Checked = Program.UserConfig.MuteNotifications;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contextMenuTray_Opened(object sender, EventArgs e){
|
private void menuItemRestore_Click(object sender, EventArgs e){
|
||||||
muteNotificationsToolStripMenuItem.CheckedChanged += muteNotificationsToolStripMenuItem_CheckedChanged;
|
ClickRestore?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreToolStripMenuItem_Click(object sender, EventArgs e){
|
private void menuItemMuteNotifications_Click(object sender, EventArgs e){
|
||||||
if (ClickRestore != null){
|
Program.UserConfig.MuteNotifications = !contextMenu.MenuItems[1].Checked;
|
||||||
ClickRestore(this, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void muteNotificationsToolStripMenuItem_CheckedChanged(object sender, EventArgs e){
|
|
||||||
Program.UserConfig.MuteNotifications = muteNotificationsToolStripMenuItem.Checked;
|
|
||||||
Program.UserConfig.Save();
|
Program.UserConfig.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeToolStripMenuItem_Click(object sender, EventArgs e){
|
private void menuItemClose_Click(object sender, EventArgs e){
|
||||||
if (ClickClose != null){
|
ClickClose?.Invoke(this, e);
|
||||||
ClickClose(this, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.IO;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDuck.Core.Utils{
|
||||||
static class BrowserCache{
|
static class BrowserCache{
|
||||||
private static bool ClearOnExit { get; set; }
|
private static bool ClearOnExit { get; set; }
|
||||||
|
|
||||||
@@ -31,21 +31,6 @@ namespace TweetDck.Core.Utils{
|
|||||||
task.Start();
|
task.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ClearOldCacheFiles(){
|
|
||||||
if (!Directory.Exists(CacheFolder)){
|
|
||||||
foreach(string file in Directory.EnumerateFiles(Program.StoragePath).Where(path => {
|
|
||||||
string file = Path.GetFileName(path);
|
|
||||||
return file != null && (file.StartsWith("data_", StringComparison.Ordinal) || file.StartsWith("f_", StringComparison.Ordinal));
|
|
||||||
}).Concat(new[]{ Path.Combine(Program.StoragePath, "index") })){
|
|
||||||
try{
|
|
||||||
File.Delete(file);
|
|
||||||
}catch{
|
|
||||||
// welp, too bad
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetClearOnExit(){
|
public static void SetClearOnExit(){
|
||||||
ClearOnExit = true;
|
ClearOnExit = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,69 @@
|
|||||||
using System;
|
using CefSharp;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDuck.Core.Utils{
|
||||||
static class BrowserUtils{
|
static class BrowserUtils{
|
||||||
public static string HeaderAcceptLanguage{
|
public static string HeaderAcceptLanguage{
|
||||||
get{
|
get{
|
||||||
string culture = CultureInfo.CurrentCulture.Name;
|
string culture = Program.Culture.Name;
|
||||||
|
|
||||||
if (culture == "en"){
|
if (culture == "en"){
|
||||||
return "en-us,en";
|
return "en-us,en";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return culture.ToLowerInvariant()+",en;q=0.9";
|
return culture.ToLower()+",en;q=0.9";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string HeaderUserAgent{
|
public static string HeaderUserAgent => Program.BrandName+" "+Application.ProductVersion;
|
||||||
get{
|
|
||||||
return Program.BrandName+" "+Application.ProductVersion;
|
public static void SetupCefArgs(IDictionary<string, string> args){
|
||||||
|
if (!Program.SystemConfig.HardwareAcceleration){
|
||||||
|
args["disable-gpu"] = "1";
|
||||||
|
args["disable-gpu-vsync"] = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
args["disable-extensions"] = "1";
|
||||||
|
args["disable-plugins-discovery"] = "1";
|
||||||
|
args["enable-system-flash"] = "0";
|
||||||
|
|
||||||
|
if (args.TryGetValue("js-flags", out string jsFlags)){
|
||||||
|
args["js-flags"] = "--expose-gc "+jsFlags;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
args["js-flags"] = "--expose-gc";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OpenExternalBrowser(string url){ // TODO implement mailto
|
public static bool IsValidUrl(string url){
|
||||||
Process.Start(url);
|
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)){
|
||||||
|
string scheme = uri.Scheme;
|
||||||
|
return scheme == Uri.UriSchemeHttp || scheme == Uri.UriSchemeHttps || scheme == Uri.UriSchemeFtp || scheme == Uri.UriSchemeMailto;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenExternalBrowser(string url){
|
||||||
|
if (string.IsNullOrWhiteSpace(url))return;
|
||||||
|
|
||||||
|
if (IsValidUrl(url)){
|
||||||
|
OpenExternalBrowserUnsafe(url);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FormMessage.Warning("Blocked URL", "A potentially malicious URL was blocked from opening:\n"+url, FormMessage.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenExternalBrowserUnsafe(string url){
|
||||||
|
using(Process.Start(url)){}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetFileNameFromUrl(string url){
|
public static string GetFileNameFromUrl(string url){
|
||||||
@@ -35,17 +71,46 @@ namespace TweetDck.Core.Utils{
|
|||||||
return string.IsNullOrEmpty(file) ? null : file;
|
return string.IsNullOrEmpty(file) ? null : file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DownloadFileAsync(string url, string target, Action<Exception> onFailure){
|
public static string GetErrorName(CefErrorCode code){
|
||||||
|
return StringUtils.ConvertPascalCaseToScreamingSnakeCase(Enum.GetName(typeof(CefErrorCode), code) ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebClient DownloadFileAsync(string url, string target, Action onSuccess, Action<Exception> onFailure){
|
||||||
WebClient client = new WebClient{ Proxy = null };
|
WebClient client = new WebClient{ Proxy = null };
|
||||||
client.Headers[HttpRequestHeader.UserAgent] = HeaderUserAgent;
|
client.Headers[HttpRequestHeader.UserAgent] = HeaderUserAgent;
|
||||||
|
|
||||||
client.DownloadFileCompleted += (sender, args) => {
|
client.DownloadFileCompleted += (sender, args) => {
|
||||||
if (args.Error != null){
|
if (args.Cancelled){
|
||||||
onFailure(args.Error);
|
try{
|
||||||
|
File.Delete(target);
|
||||||
|
}catch{
|
||||||
|
// didn't want it deleted anyways
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args.Error != null){
|
||||||
|
onFailure?.Invoke(args.Error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
onSuccess?.Invoke();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
client.DownloadFileAsync(new Uri(url), target);
|
client.DownloadFileAsync(new Uri(url), target);
|
||||||
}
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Scale(int baseValue, double scaleFactor){
|
||||||
|
return (int)Math.Round(baseValue*scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetZoomLevel(IBrowser browser, int percentage){
|
||||||
|
browser.GetHost().SetZoomLevel(Math.Log(percentage/100.0, 1.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
public static void HandleConsoleMessage(object sender, ConsoleMessageEventArgs e){
|
||||||
|
Debug.WriteLine("[Console] {0} ({1}:{2})", e.Message, e.Source, e.Line);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
|
||||||
static class CommandLineArgsParser{
|
|
||||||
private static Regex splitRegex;
|
|
||||||
|
|
||||||
private static Regex SplitRegex{
|
|
||||||
get{
|
|
||||||
return splitRegex ?? (splitRegex = new Regex(@"([^=\s]+(?:=(?:[^ ]*""[^""]*?""[^ ]*|[^ ]*))?)", RegexOptions.Compiled));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CommandLineArgs ReadCefArguments(string argumentString){
|
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(argumentString)){
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(Match match in SplitRegex.Matches(argumentString)){
|
|
||||||
string matchValue = match.Value;
|
|
||||||
|
|
||||||
int indexEquals = matchValue.IndexOf('=');
|
|
||||||
string key, value;
|
|
||||||
|
|
||||||
if (indexEquals == -1){
|
|
||||||
key = matchValue.TrimStart('-');
|
|
||||||
value = "1";
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
key = matchValue.Substring(0, indexEquals).TrimStart('-');
|
|
||||||
value = matchValue.Substring(indexEquals+1).Trim('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.Length != 0){
|
|
||||||
args.SetValue(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
|
||||||
static class HardwareAcceleration{
|
|
||||||
private static readonly string LibEGL = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libEGL.dll");
|
|
||||||
private static readonly string LibGLES = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libGLESv2.dll");
|
|
||||||
|
|
||||||
private static readonly string DisabledLibEGL = LibEGL+".bak";
|
|
||||||
private static readonly string DisabledLibGLES = LibGLES+".bak";
|
|
||||||
|
|
||||||
public static bool IsEnabled{
|
|
||||||
get{
|
|
||||||
return File.Exists(LibEGL) && File.Exists(LibGLES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanEnable{
|
|
||||||
get{
|
|
||||||
return File.Exists(DisabledLibEGL) && File.Exists(DisabledLibGLES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Enable(){
|
|
||||||
if (IsEnabled)return false;
|
|
||||||
|
|
||||||
try{
|
|
||||||
File.Move(DisabledLibEGL, LibEGL);
|
|
||||||
File.Move(DisabledLibGLES, LibGLES);
|
|
||||||
return true;
|
|
||||||
}catch{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Disable(){
|
|
||||||
if (!IsEnabled)return false;
|
|
||||||
|
|
||||||
try{
|
|
||||||
if (File.Exists(DisabledLibEGL)){
|
|
||||||
File.Delete(DisabledLibEGL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(DisabledLibGLES)){
|
|
||||||
File.Delete(DisabledLibGLES);
|
|
||||||
}
|
|
||||||
}catch{
|
|
||||||
// woops
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
|
||||||
File.Move(LibEGL, DisabledLibEGL);
|
|
||||||
File.Move(LibGLES, DisabledLibGLES);
|
|
||||||
return true;
|
|
||||||
}catch{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +1,69 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDuck.Core.Utils{
|
||||||
|
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
|
||||||
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
|
||||||
static class NativeMethods{
|
static class NativeMethods{
|
||||||
public static readonly IntPtr HWND_BROADCAST = new IntPtr(0xFFFF);
|
public static readonly IntPtr HOOK_HANDLED = new IntPtr(-1);
|
||||||
|
|
||||||
public const int HWND_TOPMOST = -1;
|
public const int HWND_TOPMOST = -1;
|
||||||
public const uint SWP_NOACTIVATE = 0x0010;
|
public const uint SWP_NOACTIVATE = 0x0010;
|
||||||
|
public const int WS_DISABLED = 0x08000000;
|
||||||
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
|
public const int GWL_STYLE = -16;
|
||||||
public const int MOUSEEVENTF_LEFTUP = 0x04;
|
|
||||||
public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
|
|
||||||
public const int MOUSEEVENTF_RIGHTUP = 0x10;
|
|
||||||
|
|
||||||
public const int SB_HORZ = 0;
|
public const int SB_HORZ = 0;
|
||||||
|
public const int BCM_SETSHIELD = 0x160C;
|
||||||
|
|
||||||
public const int WH_MOUSE_LL = 14;
|
public const int WM_MOUSE_LL = 14;
|
||||||
public const int WH_MOUSEWHEEL = 0x020A;
|
public const int WM_MOUSEWHEEL = 0x020A;
|
||||||
|
public const int WM_XBUTTONDOWN = 0x020B;
|
||||||
|
public const int WM_XBUTTONUP = 0x020C;
|
||||||
|
public const int WM_PARENTNOTIFY = 0x0210;
|
||||||
|
|
||||||
public enum MouseButton{
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
Left, Right
|
private struct LASTINPUTINFO{
|
||||||
|
public static readonly uint Size = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
|
||||||
|
|
||||||
|
public uint cbSize;
|
||||||
|
public uint dwTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct POINT{
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct MSLLHOOKSTRUCT{
|
||||||
|
public POINT pt;
|
||||||
|
public int mouseData;
|
||||||
|
public int flags;
|
||||||
|
public int time;
|
||||||
|
public UIntPtr dwExtraInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
|
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
|
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
|
||||||
public static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags);
|
private static extern bool SetWindowPos(int hWnd, int hWndOrder, int x, int y, int width, int height, uint flags);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
|
private static extern bool GetLastInputInfo(ref LASTINPUTINFO info);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
|
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern uint RegisterWindowMessage(string messageName);
|
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||||
|
|
||||||
|
[DllImport("gdi32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
@@ -50,29 +78,57 @@ namespace TweetDck.Core.Utils{
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
|
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||||
|
|
||||||
public static void SetFormPos(Form form, int hWndOrder, uint flags){
|
public static void SetFormPos(Form form, int hWndOrder, uint flags){
|
||||||
SetWindowPos(form.Handle.ToInt32(), hWndOrder, form.Left, form.Top, form.Width, form.Height, flags);
|
SetWindowPos(form.Handle.ToInt32(), hWndOrder, form.Left, form.Top, form.Width, form.Height, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SimulateMouseClick(MouseButton button){
|
public static void SetFormDisabled(Form form, bool disabled){
|
||||||
int flagHold, flagRelease;
|
if (disabled){
|
||||||
|
SetWindowLong(form.Handle, GWL_STYLE, GetWindowLong(form.Handle, GWL_STYLE) | WS_DISABLED);
|
||||||
switch(button){
|
}
|
||||||
case MouseButton.Left:
|
else{
|
||||||
flagHold = SystemInformation.MouseButtonsSwapped ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN;
|
SetWindowLong(form.Handle, GWL_STYLE, GetWindowLong(form.Handle, GWL_STYLE) & ~WS_DISABLED);
|
||||||
flagRelease = SystemInformation.MouseButtonsSwapped ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP;
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case MouseButton.Right:
|
|
||||||
flagHold = SystemInformation.MouseButtonsSwapped ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
|
|
||||||
flagRelease = SystemInformation.MouseButtonsSwapped ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_event(flagHold, Cursor.Position.X, Cursor.Position.Y, 0, 0);
|
public static int GetMouseHookData(IntPtr ptr){
|
||||||
mouse_event(flagRelease, Cursor.Position.X, Cursor.Position.Y, 0, 0);
|
return Marshal.PtrToStructure<MSLLHOOKSTRUCT>(ptr).mouseData >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetIdleSeconds(){
|
||||||
|
LASTINPUTINFO info = new LASTINPUTINFO();
|
||||||
|
info.cbSize = LASTINPUTINFO.Size;
|
||||||
|
|
||||||
|
if (!GetLastInputInfo(ref info)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ticks;
|
||||||
|
|
||||||
|
unchecked{
|
||||||
|
ticks = (uint)Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int seconds = (int)Math.Floor(TimeSpan.FromMilliseconds(ticks-info.dwTime).TotalSeconds);
|
||||||
|
return Math.Max(0, seconds); // ignore rollover after several weeks of uptime
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RenderSourceIntoBitmap(IntPtr source, Bitmap target){
|
||||||
|
using(Graphics graphics = Graphics.FromImage(target)){
|
||||||
|
IntPtr graphicsHandle = graphics.GetHdc();
|
||||||
|
|
||||||
|
try{
|
||||||
|
BitBlt(graphicsHandle, 0, 0, target.Width, target.Height, source, 0, 0, 0x00CC0020);
|
||||||
|
}finally{
|
||||||
|
graphics.ReleaseHdc(graphicsHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
Core/Utils/StringUtils.cs
Normal file
22
Core/Utils/StringUtils.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Utils{
|
||||||
|
static class StringUtils{
|
||||||
|
public static readonly string[] EmptyArray = new string[0];
|
||||||
|
|
||||||
|
public static string ExtractBefore(string str, char search, int startIndex = 0){
|
||||||
|
int index = str.IndexOf(search, startIndex);
|
||||||
|
return index == -1 ? str : str.Substring(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] ParseInts(string str, char separator){
|
||||||
|
return str.Split(new char[]{ separator }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ConvertPascalCaseToScreamingSnakeCase(string str){
|
||||||
|
return Regex.Replace(str, @"(\p{Ll})(\P{Ll})|(\P{Ll})(\P{Ll}\p{Ll})", "$1$3_$2$4").ToUpper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
Core/Utils/TwitterUtils.cs
Normal file
106
Core/Utils/TwitterUtils.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using CefSharp;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TweetDuck.Core.Other;
|
||||||
|
|
||||||
|
namespace TweetDuck.Core.Utils{
|
||||||
|
static class TwitterUtils{
|
||||||
|
public const string TweetDeckURL = "https://tweetdeck.twitter.com";
|
||||||
|
|
||||||
|
public static readonly Color BackgroundColor = Color.FromArgb(28, 99, 153);
|
||||||
|
public const string BackgroundColorFix = "let e=document.createElement('style');document.head.appendChild(e);e.innerHTML='body::before{background:#1c6399!important}'";
|
||||||
|
|
||||||
|
private static readonly Lazy<Regex> RegexAccountLazy = new Lazy<Regex>(() => new Regex(@"^https?://twitter\.com/([^/]+)/?$", RegexOptions.Compiled), false);
|
||||||
|
public static Regex RegexAccount => RegexAccountLazy.Value;
|
||||||
|
|
||||||
|
public static readonly string[] DictionaryWords = {
|
||||||
|
"tweetdeck", "TweetDeck", "tweetduck", "TweetDuck", "TD"
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum ImageQuality{
|
||||||
|
Default, Orig
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTweetDeckWebsite(IFrame frame){
|
||||||
|
return frame.Url.Contains("//tweetdeck.twitter.com/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTwitterWebsite(IFrame frame){
|
||||||
|
return frame.Url.Contains("//twitter.com/");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractImageBaseLink(string url){
|
||||||
|
int dot = url.LastIndexOf('/');
|
||||||
|
return dot == -1 ? url : StringUtils.ExtractBefore(url, ':', dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetImageLink(string url, ImageQuality quality){
|
||||||
|
if (quality == ImageQuality.Orig){
|
||||||
|
string result = ExtractImageBaseLink(url);
|
||||||
|
|
||||||
|
if (result != url || url.Contains("//pbs.twimg.com/media/")){
|
||||||
|
result += ":orig";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DownloadImage(string url, string username, ImageQuality quality){
|
||||||
|
DownloadImages(new string[]{ url }, username, quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DownloadImages(string[] urls, string username, ImageQuality quality){
|
||||||
|
if (urls.Length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string firstImageLink = GetImageLink(urls[0], quality);
|
||||||
|
int qualityIndex = firstImageLink.IndexOf(':', firstImageLink.LastIndexOf('/'));
|
||||||
|
|
||||||
|
string file = BrowserUtils.GetFileNameFromUrl(ExtractImageBaseLink(firstImageLink));
|
||||||
|
string ext = Path.GetExtension(file); // includes dot
|
||||||
|
|
||||||
|
string[] fileNameParts = qualityIndex == -1 ? new string[]{
|
||||||
|
Path.ChangeExtension(file, null)
|
||||||
|
} : new string[]{
|
||||||
|
username,
|
||||||
|
Path.ChangeExtension(file, null),
|
||||||
|
firstImageLink.Substring(qualityIndex+1)
|
||||||
|
};
|
||||||
|
|
||||||
|
using(SaveFileDialog dialog = new SaveFileDialog{
|
||||||
|
AutoUpgradeEnabled = true,
|
||||||
|
OverwritePrompt = urls.Length == 1,
|
||||||
|
Title = "Save image",
|
||||||
|
FileName = $"{string.Join(" ", fileNameParts.Where(part => part.Length > 0))}{ext}",
|
||||||
|
Filter = (urls.Length == 1 ? "Image" : "Images")+(string.IsNullOrEmpty(ext) ? " (unknown)|*.*" : $" (*{ext})|*{ext}")
|
||||||
|
}){
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK){
|
||||||
|
void OnFailure(Exception ex){
|
||||||
|
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urls.Length == 1){
|
||||||
|
BrowserUtils.DownloadFileAsync(firstImageLink, dialog.FileName, null, OnFailure);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
string pathBase = Path.ChangeExtension(dialog.FileName, null);
|
||||||
|
string pathExt = Path.GetExtension(dialog.FileName);
|
||||||
|
|
||||||
|
for(int index = 0; index < urls.Length; index++){
|
||||||
|
BrowserUtils.DownloadFileAsync(GetImageLink(urls[index], quality), $"{pathBase} {index+1}{pathExt}", null, OnFailure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +1,143 @@
|
|||||||
using System.IO;
|
using System;
|
||||||
using System.Linq;
|
using System.Diagnostics;
|
||||||
using System.Security.AccessControl;
|
using System.IO;
|
||||||
using System.Security.Principal;
|
using System.Management;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDuck.Core.Utils{
|
||||||
static class WindowsUtils{
|
static class WindowsUtils{
|
||||||
public static bool CheckFolderPermission(string path, FileSystemRights right){
|
private static readonly Lazy<Regex> RegexStripHtmlStyles = new Lazy<Regex>(() => new Regex(@"\s?(?:style|class)="".*?"""), false);
|
||||||
|
private static readonly Lazy<Regex> RegexOffsetClipboardHtml = new Lazy<Regex>(() => new Regex(@"(?<=EndHTML:|EndFragment:)(\d+)"), false);
|
||||||
|
|
||||||
|
public static int CurrentProcessID { get; }
|
||||||
|
public static bool ShouldAvoidToolWindow { get; }
|
||||||
|
|
||||||
|
static WindowsUtils(){
|
||||||
|
using(Process me = Process.GetCurrentProcess()){
|
||||||
|
CurrentProcessID = me.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Version ver = Environment.OSVersion.Version;
|
||||||
|
ShouldAvoidToolWindow = ver.Major == 6 && ver.Minor == 2; // windows 8/10
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateDirectoryForFile(string file){
|
||||||
|
string dir = Path.GetDirectoryName(file);
|
||||||
|
|
||||||
|
if (dir == null){
|
||||||
|
throw new ArgumentException("Invalid file path: "+file);
|
||||||
|
}
|
||||||
|
else if (dir.Length > 0){
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckFolderWritePermission(string path){
|
||||||
|
string testFile = Path.Combine(path, ".test");
|
||||||
|
|
||||||
try{
|
try{
|
||||||
AuthorizationRuleCollection rules = Directory.GetAccessControl(path).GetAccessRules(true, true, typeof(SecurityIdentifier));
|
Directory.CreateDirectory(path);
|
||||||
WindowsIdentity identity = WindowsIdentity.GetCurrent();
|
|
||||||
|
|
||||||
if (identity == null || identity.Groups == null){
|
using(File.Create(testFile)){}
|
||||||
return false;
|
File.Delete(testFile);
|
||||||
}
|
return true;
|
||||||
|
}catch{
|
||||||
bool accessAllow = false, accessDeny = false;
|
|
||||||
|
|
||||||
foreach(FileSystemAccessRule rule in rules.Cast<FileSystemAccessRule>().Where(rule => identity.Groups.Contains(rule.IdentityReference) && (right & rule.FileSystemRights) == right)){
|
|
||||||
switch(rule.AccessControlType){
|
|
||||||
case AccessControlType.Allow: accessAllow = true; break;
|
|
||||||
case AccessControlType.Deny: accessDeny = true; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return accessAllow && !accessDeny;
|
|
||||||
}
|
|
||||||
catch{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Process StartProcess(string file, string arguments, bool runElevated){
|
||||||
|
ProcessStartInfo processInfo = new ProcessStartInfo{
|
||||||
|
FileName = file,
|
||||||
|
Arguments = arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
if (runElevated){
|
||||||
|
processInfo.Verb = "runas";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Process.Start(processInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TrySleepUntil(Func<bool> test, int timeoutMillis, int timeStepMillis){
|
||||||
|
for(int waited = 0; waited < timeoutMillis; waited += timeStepMillis){
|
||||||
|
if (test()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(timeStepMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TryDeleteFolderWhenAble(string path, int timeout){
|
||||||
|
new Thread(() => {
|
||||||
|
TrySleepUntil(() => {
|
||||||
|
try{
|
||||||
|
Directory.Delete(path, true);
|
||||||
|
return true;
|
||||||
|
}catch(DirectoryNotFoundException){
|
||||||
|
return true;
|
||||||
|
}catch{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, timeout, 500);
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsChildProcess(int pid){
|
||||||
|
try{
|
||||||
|
using(ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = "+pid)){
|
||||||
|
foreach(ManagementBaseObject obj in searcher.Get()){
|
||||||
|
return (uint)obj["ParentProcessId"] == CurrentProcessID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}catch{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClipboardStripHtmlStyles(){
|
||||||
|
if (!Clipboard.ContainsText(TextDataFormat.Html)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string originalText = Clipboard.GetText(TextDataFormat.UnicodeText);
|
||||||
|
string originalHtml = Clipboard.GetText(TextDataFormat.Html);
|
||||||
|
|
||||||
|
string updatedHtml = RegexStripHtmlStyles.Value.Replace(originalHtml, string.Empty);
|
||||||
|
|
||||||
|
int removed = originalHtml.Length-updatedHtml.Length;
|
||||||
|
updatedHtml = RegexOffsetClipboardHtml.Value.Replace(updatedHtml, match => (int.Parse(match.Value)-removed).ToString().PadLeft(match.Value.Length, '0'));
|
||||||
|
|
||||||
|
DataObject obj = new DataObject();
|
||||||
|
obj.SetText(originalText, TextDataFormat.UnicodeText);
|
||||||
|
obj.SetText(updatedHtml, TextDataFormat.Html);
|
||||||
|
SetClipboardData(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetClipboard(string text, TextDataFormat format){
|
||||||
|
if (string.IsNullOrEmpty(text)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataObject obj = new DataObject();
|
||||||
|
obj.SetText(text, format);
|
||||||
|
SetClipboardData(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetClipboardData(DataObject obj){
|
||||||
|
try{
|
||||||
|
Clipboard.SetDataObject(obj);
|
||||||
|
}catch(ExternalException e){
|
||||||
|
Program.Reporter.HandleException("Clipboard Error", "TweetDuck could not access the clipboard as it is currently used by another process.", true, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using TweetDuck.Core.Utils;
|
||||||
|
|
||||||
namespace TweetDck.Core.Other.Settings.Export{
|
namespace TweetDuck.Data{
|
||||||
class CombinedFileStream : IDisposable{
|
sealed class CombinedFileStream : IDisposable{
|
||||||
public const char KeySeparator = '/';
|
public const char KeySeparator = '|';
|
||||||
|
|
||||||
private readonly Stream stream;
|
private readonly Stream stream;
|
||||||
|
|
||||||
@@ -12,6 +13,10 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteFile(string[] identifier, string path){
|
||||||
|
WriteFile(string.Join(KeySeparator.ToString(), identifier), path);
|
||||||
|
}
|
||||||
|
|
||||||
public void WriteFile(string identifier, string path){
|
public void WriteFile(string identifier, string path){
|
||||||
byte[] name = Encoding.UTF8.GetBytes(identifier);
|
byte[] name = Encoding.UTF8.GetBytes(identifier);
|
||||||
|
|
||||||
@@ -59,6 +64,25 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
return new Entry(Encoding.UTF8.GetString(name), contents);
|
return new Entry(Encoding.UTF8.GetString(name), contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SkipFile(){
|
||||||
|
int nameLength = stream.ReadByte();
|
||||||
|
|
||||||
|
if (nameLength == -1){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] name = new byte[nameLength];
|
||||||
|
stream.Read(name, 0, nameLength);
|
||||||
|
|
||||||
|
byte[] contentLength = new byte[4];
|
||||||
|
stream.Read(contentLength, 0, 4);
|
||||||
|
|
||||||
|
stream.Position += BitConverter.ToInt32(contentLength, 0);
|
||||||
|
|
||||||
|
string keyName = Encoding.UTF8.GetString(name);
|
||||||
|
return StringUtils.ExtractBefore(keyName, KeySeparator);
|
||||||
|
}
|
||||||
|
|
||||||
public void Flush(){
|
public void Flush(){
|
||||||
stream.Flush();
|
stream.Flush();
|
||||||
}
|
}
|
||||||
@@ -68,12 +92,18 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Entry{
|
public class Entry{
|
||||||
public string Identifier { get; private set; }
|
public string Identifier { get; }
|
||||||
|
|
||||||
public string KeyName{
|
public string KeyName{
|
||||||
|
get{
|
||||||
|
return StringUtils.ExtractBefore(Identifier, KeySeparator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] KeyValue{
|
||||||
get{
|
get{
|
||||||
int index = Identifier.IndexOf(KeySeparator);
|
int index = Identifier.IndexOf(KeySeparator);
|
||||||
return index == -1 ? Identifier : Identifier.Substring(0, index);
|
return index == -1 ? StringUtils.EmptyArray : Identifier.Substring(index+1).Split(KeySeparator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +120,7 @@ namespace TweetDck.Core.Other.Settings.Export{
|
|||||||
|
|
||||||
public void WriteToFile(string path, bool createDirectory){
|
public void WriteToFile(string path, bool createDirectory){
|
||||||
if (createDirectory){
|
if (createDirectory){
|
||||||
// ReSharper disable once AssignNullToNotNullAttribute
|
WindowsUtils.CreateDirectoryForFile(path);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File.WriteAllBytes(path, contents);
|
File.WriteAllBytes(path, contents);
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace TweetDck.Core.Utils{
|
namespace TweetDuck.Data{
|
||||||
class CommandLineArgs{
|
sealed class CommandLineArgs{
|
||||||
public static CommandLineArgs FromStringArray(char entryChar, string[] array){
|
public static CommandLineArgs FromStringArray(char entryChar, string[] array){
|
||||||
CommandLineArgs args = new CommandLineArgs();
|
CommandLineArgs args = new CommandLineArgs();
|
||||||
ReadStringArray(entryChar, array, args);
|
ReadStringArray(entryChar, array, args);
|
||||||
@@ -32,38 +33,67 @@ namespace TweetDck.Core.Utils{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CommandLineArgs ReadCefArguments(string argumentString){
|
||||||
|
CommandLineArgs args = new CommandLineArgs();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(argumentString)){
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(Match match in Regex.Matches(argumentString, @"([^=\s]+(?:=(?:\S*""[^""]*?""\S*|\S*))?)")){
|
||||||
|
string matchValue = match.Value;
|
||||||
|
|
||||||
|
int indexEquals = matchValue.IndexOf('=');
|
||||||
|
string key, value;
|
||||||
|
|
||||||
|
if (indexEquals == -1){
|
||||||
|
key = matchValue.TrimStart('-');
|
||||||
|
value = "1";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
key = matchValue.Substring(0, indexEquals).TrimStart('-');
|
||||||
|
value = matchValue.Substring(indexEquals+1).Trim('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.Length != 0){
|
||||||
|
args.SetValue(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
private readonly HashSet<string> flags = new HashSet<string>();
|
private readonly HashSet<string> flags = new HashSet<string>();
|
||||||
private readonly Dictionary<string, string> values = new Dictionary<string, string>();
|
private readonly Dictionary<string, string> values = new Dictionary<string, string>();
|
||||||
|
|
||||||
public int Count{
|
public int Count => flags.Count+values.Count;
|
||||||
get{
|
|
||||||
return flags.Count+values.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddFlag(string flag){
|
public void AddFlag(string flag){
|
||||||
flags.Add(flag.ToLowerInvariant());
|
flags.Add(flag.ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasFlag(string flag){
|
public bool HasFlag(string flag){
|
||||||
return flags.Contains(flag.ToLowerInvariant());
|
return flags.Contains(flag.ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveFlag(string flag){
|
public void RemoveFlag(string flag){
|
||||||
flags.Remove(flag.ToLowerInvariant());
|
flags.Remove(flag.ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(string key, string value){
|
public void SetValue(string key, string value){
|
||||||
values[key.ToLowerInvariant()] = value;
|
values[key.ToLower()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasValue(string key){
|
||||||
|
return values.ContainsKey(key.ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetValue(string key, string defaultValue){
|
public string GetValue(string key, string defaultValue){
|
||||||
string val;
|
return values.TryGetValue(key.ToLower(), out string val) ? val : defaultValue;
|
||||||
return values.TryGetValue(key.ToLowerInvariant(), out val) ? val : defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveValue(string key){
|
public void RemoveValue(string key){
|
||||||
values.Remove(key.ToLowerInvariant());
|
values.Remove(key.ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandLineArgs Clone(){
|
public CommandLineArgs Clone(){
|
||||||
@@ -101,7 +131,7 @@ namespace TweetDck.Core.Utils{
|
|||||||
build.Append(kvp.Key).Append(" \"").Append(kvp.Value).Append("\" ");
|
build.Append(kvp.Key).Append(" \"").Append(kvp.Value).Append("\" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return build.Remove(build.Length-1, 1).ToString();
|
return build.Length == 0 ? string.Empty : build.Remove(build.Length-1, 1).ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
37
Data/InjectedHTML.cs
Normal file
37
Data/InjectedHTML.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDuck.Data{
|
||||||
|
sealed class InjectedHTML{
|
||||||
|
public enum Position{
|
||||||
|
Before, After
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Position position;
|
||||||
|
private readonly string search;
|
||||||
|
private readonly string html;
|
||||||
|
|
||||||
|
public InjectedHTML(Position position, string search, string html){
|
||||||
|
this.position = position;
|
||||||
|
this.search = search;
|
||||||
|
this.html = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Inject(string targetHTML){
|
||||||
|
int index = targetHTML.IndexOf(search, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
return targetHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cutIndex;
|
||||||
|
|
||||||
|
switch(position){
|
||||||
|
case Position.Before: cutIndex = index; break;
|
||||||
|
case Position.After: cutIndex = index+search.Length; break;
|
||||||
|
default: return targetHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetHTML.Insert(cutIndex, html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
146
Data/Serialization/FileSerializer.cs
Normal file
146
Data/Serialization/FileSerializer.cs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace TweetDuck.Data.Serialization{
|
||||||
|
sealed class FileSerializer<T>{
|
||||||
|
private const string NewLineReal = "\r\n";
|
||||||
|
private const string NewLineCustom = "\r~\n";
|
||||||
|
|
||||||
|
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
|
||||||
|
|
||||||
|
public delegate void HandleUnknownPropertiesHandler(T obj, Dictionary<string, string> data);
|
||||||
|
public HandleUnknownPropertiesHandler HandleUnknownProperties { get; set; }
|
||||||
|
|
||||||
|
private readonly Dictionary<string, PropertyInfo> props;
|
||||||
|
private readonly Dictionary<Type, ITypeConverter> converters;
|
||||||
|
|
||||||
|
public FileSerializer(){
|
||||||
|
this.props = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(prop => prop.CanWrite).ToDictionary(prop => prop.Name);
|
||||||
|
this.converters = new Dictionary<Type, ITypeConverter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterTypeConverter(Type type, ITypeConverter converter){
|
||||||
|
converters[type] = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(string file, T obj){
|
||||||
|
using(StreamWriter writer = new StreamWriter(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))){
|
||||||
|
foreach(KeyValuePair<string, PropertyInfo> prop in props){
|
||||||
|
Type type = prop.Value.PropertyType;
|
||||||
|
object value = prop.Value.GetValue(obj);
|
||||||
|
|
||||||
|
if (!converters.TryGetValue(type, out ITypeConverter serializer)) {
|
||||||
|
serializer = BasicSerializerObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serializer.TryWriteType(type, value, out string converted)){
|
||||||
|
if (converted != null){
|
||||||
|
writer.Write($"{prop.Key} {converted.Replace(Environment.NewLine, NewLineCustom)}");
|
||||||
|
writer.Write(NewLineReal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new SerializationException($"Invalid serialization type, conversion failed for: {type}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Read(string file, T obj){
|
||||||
|
Dictionary<string, string> unknownProperties = new Dictionary<string, string>(4);
|
||||||
|
|
||||||
|
using(StreamReader reader = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))){
|
||||||
|
if (reader.Peek() <= 1){
|
||||||
|
throw new FormatException("Input appears to be a binary file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(string line in reader.ReadToEnd().Split(new string[]{ NewLineReal }, StringSplitOptions.RemoveEmptyEntries)){
|
||||||
|
int space = line.IndexOf(' ');
|
||||||
|
|
||||||
|
if (space == -1){
|
||||||
|
throw new SerializationException($"Invalid file format, missing separator: {line}");
|
||||||
|
}
|
||||||
|
|
||||||
|
string property = line.Substring(0, space);
|
||||||
|
string value = line.Substring(space+1).Replace(NewLineCustom, Environment.NewLine);
|
||||||
|
|
||||||
|
if (props.TryGetValue(property, out PropertyInfo info)){
|
||||||
|
if (!converters.TryGetValue(info.PropertyType, out ITypeConverter serializer)) {
|
||||||
|
serializer = BasicSerializerObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serializer.TryReadType(info.PropertyType, value, out object converted)){
|
||||||
|
info.SetValue(obj, converted);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new SerializationException($"Invalid file format, cannot convert value: {value} (property: {property})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
unknownProperties[property] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unknownProperties.Count > 0){
|
||||||
|
HandleUnknownProperties?.Invoke(obj, unknownProperties);
|
||||||
|
|
||||||
|
if (unknownProperties.Count > 0){
|
||||||
|
throw new SerializationException($"Invalid file format, unknown properties: {string.Join(", ", unknownProperties.Keys)}+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BasicTypeConverter : ITypeConverter{
|
||||||
|
bool ITypeConverter.TryWriteType(Type type, object value, out string converted){
|
||||||
|
switch(Type.GetTypeCode(type)){
|
||||||
|
case TypeCode.Boolean:
|
||||||
|
converted = value.ToString();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case TypeCode.Int32:
|
||||||
|
converted = ((int)value).ToString(); // cast required for enums
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case TypeCode.String:
|
||||||
|
converted = value?.ToString();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
converted = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ITypeConverter.TryReadType(Type type, string value, out object converted){
|
||||||
|
switch(Type.GetTypeCode(type)){
|
||||||
|
case TypeCode.Boolean:
|
||||||
|
if (bool.TryParse(value, out bool b)){
|
||||||
|
converted = b;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else goto default;
|
||||||
|
|
||||||
|
case TypeCode.Int32:
|
||||||
|
if (int.TryParse(value, out int i)){
|
||||||
|
converted = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else goto default;
|
||||||
|
|
||||||
|
case TypeCode.String:
|
||||||
|
converted = value;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
converted = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Data/Serialization/ITypeConverter.cs
Normal file
8
Data/Serialization/ITypeConverter.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TweetDuck.Data.Serialization{
|
||||||
|
interface ITypeConverter{
|
||||||
|
bool TryWriteType(Type type, object value, out string converted);
|
||||||
|
bool TryReadType(Type type, string value, out object converted);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user