Merged lindenlab/viewer-development into default

master
graham linden 2013-03-28 19:16:48 -07:00
commit 14ddfcdf52
72 changed files with 1452 additions and 645 deletions

134
.hgtags
View File

@ -72,35 +72,35 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 DRTVWR-38_2.5.2-release
461c8c65b5c799ddfe365422f9be9c0095d91e7d 2.6.0-beta1-tip 461c8c65b5c799ddfe365422f9be9c0095d91e7d 2.6.0-beta1-tip
9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2 9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2
9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2 9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2
42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1 c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start
c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1 c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1
c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start 56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start
d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1 d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1
d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1 d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1
214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release 42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release 42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py 52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py
ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1 d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1 d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1
0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2 0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2
0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2 0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2
8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work 3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work
214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release
214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1 7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1 7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1
8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start 800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1 bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1 bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1
5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
dac76a711da5f1489a01c1fa62ec97d99c25736d DRTVWR-51_2.6.6-release dac76a711da5f1489a01c1fa62ec97d99c25736d DRTVWR-51_2.6.6-release
5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1 beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1
beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1 beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1
be2000b946f8cb3de5f44b2d419287d4c48ec4eb 2.6.8-release be2000b946f8cb3de5f44b2d419287d4c48ec4eb 2.6.8-release
@ -119,50 +119,50 @@ e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start 9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1 e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1 e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start 6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start
be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1 be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1
be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1 be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1
057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start 19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start
09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1 09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1 e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release 057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release 057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1 2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1 2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release 29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release 29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix 4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix
4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix 4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1 599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1
599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1 599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1
fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start 6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start
b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1 b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1
b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1 b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1
1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start 82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start
364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1 364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1
364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1 364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1
f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start
42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1 42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1
42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1 42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1
1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2 e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2 e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2
b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
@ -170,9 +170,9 @@ b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2 61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2 61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
586907287be581817b2422b5137971b22d54ea48 3.0.4-start
0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release 0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release
0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release 0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release
586907287be581817b2422b5137971b22d54ea48 3.0.4-start
92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start 92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start
c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1 2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1
@ -193,11 +193,11 @@ e440cd1dfbd128d7d5467019e497f7f803640ad6 DRTVWR-95_3.2.0-beta1
c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
9e390d76807fa70d356b8716fb83b8ce42a629ef 3.2.1-beta1 9e390d76807fa70d356b8716fb83b8ce42a629ef 3.2.1-beta1
9e390d76807fa70d356b8716fb83b8ce42a629ef DRTVWR-100_3.2.1-beta1 9e390d76807fa70d356b8716fb83b8ce42a629ef DRTVWR-100_3.2.1-beta1
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
40b46edba007d15d0059c80864b708b99c1da368 3.2.2-start 40b46edba007d15d0059c80864b708b99c1da368 3.2.2-start
523df3e67378541498d516d52af4402176a26bac 3.2.2-beta1 523df3e67378541498d516d52af4402176a26bac 3.2.2-beta1
523df3e67378541498d516d52af4402176a26bac DRTVWR-102_3.2.2-beta1 523df3e67378541498d516d52af4402176a26bac DRTVWR-102_3.2.2-beta1
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start 80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start 3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
@ -248,68 +248,57 @@ bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156
6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148 6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148
2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155 2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155
24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153 24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153
a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160 5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1 f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144 f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144
089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162
c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164 2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162
80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165 80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165
fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2 fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2
af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169 af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169
4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3 4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3
6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release 6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release
a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171 b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171
050e48759337249130f684b4a21080b683f61732 DRTVWR-168 050e48759337249130f684b4a21080b683f61732 DRTVWR-168
09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170 09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170
f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158 f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158
f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1 f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1
005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173 bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173
cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174 cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174
82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2 82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2
57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176 57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176
eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177 eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177
a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3 a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3
888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180 4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180
5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183 5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183
6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4 6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4
9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184 9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184
ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5 ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5
28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release 28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release
005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182 a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182
1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1 1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1
81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190
cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
9ee9387789701d597130f879d9011a4958753862 DRTVWR-189 9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190
421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192 421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192
4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195 33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195
e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193 e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193
78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196 7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196
ae5c83dd61d2d37c45f1d5b8bf2b036d87599f1b DRTVWR-198 ae5c83dd61d2d37c45f1d5b8bf2b036d87599f1b DRTVWR-198
507bdfbd6bf844a511c1ffeda4baa80016ed1346 DRTVWR-197 507bdfbd6bf844a511c1ffeda4baa80016ed1346 DRTVWR-197
b1dbb1a83f48f93f6f878cff9e52d2cb635e145c 3.4.0-beta2 b1dbb1a83f48f93f6f878cff9e52d2cb635e145c 3.4.0-beta2
37402e2b19af970d51b0a814d79892cc5647532b DRTVWR-200 37402e2b19af970d51b0a814d79892cc5647532b DRTVWR-200
182a9bf30e81070361bb020a78003b1cf398e79c 3.4.0-beta3 182a9bf30e81070361bb020a78003b1cf398e79c 3.4.0-beta3
248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
6dfb0fba782c9233dd95f24ec48146db0d3f210b DRTVWR-199 6dfb0fba782c9233dd95f24ec48146db0d3f210b DRTVWR-199
7c9102fb998885621919f2474a002c35b583539b 3.3.4-release2 7c9102fb998885621919f2474a002c35b583539b 3.3.4-release2
7649a3dff5ec22d3727377e5f02efd0f421e4cb5 DRTVWR-201 7649a3dff5ec22d3727377e5f02efd0f421e4cb5 DRTVWR-201
84fb70dfe3444e75a44fb4bee43e2fc8221cebdd 3.4.0-beta4 84fb70dfe3444e75a44fb4bee43e2fc8221cebdd 3.4.0-beta4
de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
092a9effbedd1a0276fa5ced520992ce00f96fbf CHUI-PV-0
573e863be2f26d3687161def4b9fea9b7038dda8 3.4.0-beta5 573e863be2f26d3687161def4b9fea9b7038dda8 3.4.0-beta5
34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
8c9085066c78ed5f6c9379dc054c82a6fcdb1851 DRTVWR-207 8c9085066c78ed5f6c9379dc054c82a6fcdb1851 DRTVWR-207
351eea5f9dc192fc5ddea3b02958de97677a0a12 3.3.4-release3 351eea5f9dc192fc5ddea3b02958de97677a0a12 3.3.4-release3
af7b28e75bd5a629cd9e0dc46fb3f1757626f493 DRTVWR-212 af7b28e75bd5a629cd9e0dc46fb3f1757626f493 DRTVWR-212
@ -320,7 +309,6 @@ ceed0b65a69f1eac20d523e0203320a32f9a3f3c DRTVWR-215
97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release 97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release
5adb2b8f96c3cac88ad7c7d996d707f1b29df336 3.4.1-beta1 5adb2b8f96c3cac88ad7c7d996d707f1b29df336 3.4.1-beta1
b3f74858a1c8720c82d0978f3877a3fc8ba459ec 3.4.1-beta1a b3f74858a1c8720c82d0978f3877a3fc8ba459ec 3.4.1-beta1a
b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
2b779f233ee6f38c89cb921650c773a96e63da92 DRTVWR-220 2b779f233ee6f38c89cb921650c773a96e63da92 DRTVWR-220
0b9d95f4bfb6867cbf56eaec51633b0da2f1262d DRTVWR-221 0b9d95f4bfb6867cbf56eaec51633b0da2f1262d DRTVWR-221
e6e553761829dc0270eaaa712b7cb0622535b076 3.4.1-beta3 e6e553761829dc0270eaaa712b7cb0622535b076 3.4.1-beta3
@ -345,31 +333,36 @@ baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236
b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237
3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12 3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12
e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release
81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217 32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217
704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1 704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1
d799593b53ed733862e9a13871e318e886469377 DRTVWR-208
e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223
288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216 288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216
e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2 e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2
93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240
0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242 0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3 710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
f7bedce18ad52283e6072814db23318907261487 DRTVWR-238
7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210
e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243 e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243
73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4 73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4
16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release 16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release
d799593b53ed733862e9a13871e318e886469377 DRTVWR-208
e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223
93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240
2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
f7bedce18ad52283e6072814db23318907261487 DRTVWR-238
7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210
5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241 5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241
f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232 f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232
4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245 4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245
94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1 94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1
4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252 965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252
bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251 bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251
ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
@ -378,25 +371,31 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258 44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258
c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257
452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259 452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259
9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265 daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265
9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266 9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266
73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267 73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267
870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3 870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3
0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release 0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release
4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244
083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1
391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270
cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2
2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271
2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3
35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273
a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275 c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275
05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4 05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4
e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release
391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250 7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250
b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277 b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277
af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276 af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276
@ -406,8 +405,6 @@ c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280
5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281 5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281
7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283 7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283
6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2 6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2
37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282
6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284
ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286 ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286
2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287 2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287
e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3 e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3
@ -420,6 +417,17 @@ b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292
0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297 0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297
852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5 852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5
a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release
37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282
6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284
092a9effbedd1a0276fa5ced520992ce00f96fbf CHUI-PV-0
279ef1dfc9b749a6cc499cf190fec0c090b6d682 DRTVWR-288 279ef1dfc9b749a6cc499cf190fec0c090b6d682 DRTVWR-288
9b19edaf1d8ddf435f60fbbb444dd25db8f63953 3.5.0-beta1 9b19edaf1d8ddf435f60fbbb444dd25db8f63953 3.5.0-beta1
c6b3561c7d7ad365eeba669db54eb57b5149ce75 3.5.0-beta2 c6b3561c7d7ad365eeba669db54eb57b5149ce75 3.5.0-beta2
6d91ffd77bf2a20f18a2175eb7579da880ae12ac DRTVWR-302
f6ca5bb75bca975ff0bc77e71e615f6478c4559c 3.5.0-beta3
910b5fad950e343b58229f5a0aefa7729b9308b3 DRTVWR-303
53cffdde0b3cc367ba9bb6abd5c83ae14df5e882 3.5.0-beta4
4d5f6234dc59a0fb6ead5e02c7d343a0610e0488 DRTVWR-304
dd058a6093c493120d67c8e02c812c0f7b2d3db0 3.5.0-beta5
fd6b510e83f56830e45670c428653134899d3e25 DRTVWR-305
55339537d99afc394d1bb7fdb7d074bf321ca62f 3.5.0-beta6

View File

@ -744,6 +744,7 @@ Marc Claridge
Marc2 Sands Marc2 Sands
Marianne McCann Marianne McCann
Marine Kelley Marine Kelley
CHUIBUG-134
STORM-281 STORM-281
MartinRJ Fayray MartinRJ Fayray
STORM-1844 STORM-1844

View File

@ -599,6 +599,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if(!fgi) if(!fgi)
{ {
fgi = mFontFreetype->getGlyphInfo(wch); fgi = mFontFreetype->getGlyphInfo(wch);
if (NULL == fgi)
{
return 0;
}
} }
// account for glyphs that run beyond the starting point for the next glyphs // account for glyphs that run beyond the starting point for the next glyphs

View File

@ -597,11 +597,6 @@ bool LLGLManager::initGL()
if (mGLVendor.substr(0,4) == "ATI ") if (mGLVendor.substr(0,4) == "ATI ")
{ {
mGLVendorShort = "ATI"; mGLVendorShort = "ATI";
BOOL mobile = FALSE;
if (mGLRenderer.find("MOBILITY") != std::string::npos)
{
mobile = TRUE;
}
mIsATI = TRUE; mIsATI = TRUE;
#if LL_WINDOWS && !LL_MESA_HEADLESS #if LL_WINDOWS && !LL_MESA_HEADLESS
@ -1489,9 +1484,7 @@ void assert_glerror()
void clear_glerror() void clear_glerror()
{ {
// Create or update texture to be used with this data glGetError();
GLenum error;
error = glGetError();
} }
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////

View File

@ -169,6 +169,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{ {
BOOL handled = FALSE; BOOL handled = FALSE;
// In the case of a chat entry, pressing RETURN when something is selected
// should NOT erase the selection (unlike a notecard, for example)
if (key == KEY_RETURN)
{
endOfDoc();
startSelection();
endSelection();
}
LLTextEditor::handleSpecialKey(key, mask); LLTextEditor::handleSpecialKey(key, mask);
switch(key) switch(key)

View File

@ -1621,7 +1621,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual // virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus) void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{ {
LLMultiFloater* hostp = getHost(); LLMultiFloater* hostp = getHost();
if (hostp) if (hostp)

View File

@ -305,7 +305,7 @@ public:
/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
void setFrontmost(BOOL take_focus = TRUE); void setFrontmost(BOOL take_focus = TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
// Defaults to false. // Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; } virtual BOOL canSaveAs() const { return FALSE; }

View File

@ -488,12 +488,12 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
{ {
host->setMinimized(FALSE); host->setMinimized(FALSE);
instance->openFloater(key); instance->openFloater(key);
instance->setVisibleAndFrontmost(); instance->setVisibleAndFrontmost(true, key);
} }
else if (!instance->getVisible()) else if (!instance->getVisible())
{ {
instance->openFloater(key); instance->openFloater(key);
instance->setVisibleAndFrontmost(); instance->setVisibleAndFrontmost(true, key);
instance->setFocus(TRUE); instance->setFocus(TRUE);
} }
else else
@ -506,16 +506,16 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
if (instance->isMinimized()) if (instance->isMinimized())
{ {
instance->setMinimized(FALSE); instance->setMinimized(FALSE);
instance->setVisibleAndFrontmost(); instance->setVisibleAndFrontmost(true, key);
} }
else if (!instance->isShown()) else if (!instance->isShown())
{ {
instance->openFloater(key); instance->openFloater(key);
instance->setVisibleAndFrontmost(); instance->setVisibleAndFrontmost(true, key);
} }
else if (!instance->isFrontmost()) else if (!instance->isFrontmost())
{ {
instance->setVisibleAndFrontmost(); instance->setVisibleAndFrontmost(true, key);
} }
else else
{ {

View File

@ -202,6 +202,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
LLLineEditor::~LLLineEditor() LLLineEditor::~LLLineEditor()
{ {
mCommitOnFocusLost = FALSE; mCommitOnFocusLost = FALSE;
// Make sure no context menu linger around once the widget is deleted
LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
if (menu)
{
menu->hide();
}
setContextMenu(NULL);
// calls onCommit() while LLLineEditor still valid // calls onCommit() while LLLineEditor still valid
gFocusMgr.releaseFocusIfNeeded( this ); gFocusMgr.releaseFocusIfNeeded( this );

View File

@ -1801,6 +1801,9 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
// (N.B. callbacks don't take const refs as id is local scope) // (N.B. callbacks don't take const refs as id is local scope)
bool is_group = (mContextMenuType == MENU_GROUP); bool is_group = (mContextMenuType == MENU_GROUP);
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Url.ShowProfile", boost::bind(&LLScrollListCtrl::showProfile, id, is_group));
registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id));
registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id));
registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group)); registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group)); registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group)); registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
@ -1821,11 +1824,33 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
return FALSE; return FALSE;
} }
void LLScrollListCtrl::showNameDetails(std::string id, bool is_group) void LLScrollListCtrl::showProfile(std::string id, bool is_group)
{ {
// show the resident's profile or the group profile // show the resident's profile or the group profile
std::string sltype = is_group ? "group" : "agent"; std::string sltype = is_group ? "group" : "agent";
std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about"; std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
LLUrlAction::showProfile(slurl);
}
void LLScrollListCtrl::sendIM(std::string id)
{
// send im to the resident
std::string slurl = "secondlife:///app/agent/" + id + "/about";
LLUrlAction::sendIM(slurl);
}
void LLScrollListCtrl::addFriend(std::string id)
{
// add resident to friends list
std::string slurl = "secondlife:///app/agent/" + id + "/about";
LLUrlAction::addFriend(slurl);
}
void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
{
// open the resident's details or the group details
std::string sltype = is_group ? "group" : "agent";
std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
LLUrlAction::clickAction(slurl); LLUrlAction::clickAction(slurl);
} }

View File

@ -430,6 +430,9 @@ private:
BOOL setSort(S32 column, BOOL ascending); BOOL setSort(S32 column, BOOL ascending);
S32 getLinesPerPage(); S32 getLinesPerPage();
static void showProfile(std::string id, bool is_group);
static void sendIM(std::string id);
static void addFriend(std::string id);
static void showNameDetails(std::string id, bool is_group); static void showNameDetails(std::string id, bool is_group);
static void copyNameToClipboard(std::string id, bool is_group); static void copyNameToClipboard(std::string id, bool is_group);
static void copySLURLToClipboard(std::string id, bool is_group); static void copySLURLToClipboard(std::string id, bool is_group);

View File

@ -1483,16 +1483,22 @@ BOOL LLTabContainer::setTab(S32 which)
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{ {
LLTabTuple* tuple = *iter; LLTabTuple* tuple = *iter;
if (!tuple)
continue;
BOOL is_selected = ( tuple == selected_tuple ); BOOL is_selected = ( tuple == selected_tuple );
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign); // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list
tuple->mTabPanel->setVisible( is_selected ); if (tuple->mButton)
// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here. {
tuple->mButton->setToggleState( is_selected ); tuple->mButton->setUseEllipses(mUseTabEllipses);
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs tuple->mButton->setHAlign(mFontHalign);
tuple->mButton->setTabStop( is_selected ); tuple->mButton->setToggleState( is_selected );
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
tuple->mButton->setTabStop( is_selected );
}
if (tuple->mTabPanel)
{
tuple->mTabPanel->setVisible( is_selected );
//tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
}
if (is_selected) if (is_selected)
{ {
@ -1563,8 +1569,7 @@ BOOL LLTabContainer::selectTabByName(const std::string& name)
LLPanel* panel = getPanelByName(name); LLPanel* panel = getPanelByName(name);
if (!panel) if (!panel)
{ {
llwarns << "LLTabContainer::selectTabByName(" llwarns << "LLTabContainer::selectTabByName(" << name << ") failed" << llendl;
<< name << ") failed" << llendl;
return FALSE; return FALSE;
} }

View File

@ -359,7 +359,6 @@ void LLTextBase::drawSelectionBackground()
S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
LLRect selection_rect = mVisibleTextRect;
// Skip through the lines we aren't drawing. // Skip through the lines we aren't drawing.
LLRect content_display_rect = getVisibleDocumentRect(); LLRect content_display_rect = getVisibleDocumentRect();
@ -1086,7 +1085,14 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask) BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{ {
mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL); //Don't start triple click timer if user have clicked on scrollbar
mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
if (x >= mVisibleTextRect.mLeft && x <= mVisibleTextRect.mRight
&& y >= mVisibleTextRect.mBottom && y <= mVisibleTextRect.mTop)
{
mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
}
LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y); LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleDoubleClick(x, y, mask)) if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
{ {
@ -1912,6 +1918,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
@ -2330,7 +2337,6 @@ const LLWString& LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{ {
// Figure out which line we're nearest to. // Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
LLRect doc_rect = mDocumentView->getRect(); LLRect doc_rect = mDocumentView->getRect();
S32 doc_y = local_y - doc_rect.mBottom; S32 doc_y = local_y - doc_rect.mBottom;
@ -3195,7 +3201,23 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0) LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0)
? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE ? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE
: LLFontGL::ONLY_WORD_BOUNDARIES; : LLFontGL::ONLY_WORD_BOUNDARIES;
S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
LLWString offsetString(text.c_str() + segment_offset + mStart);
if(getLength() < segment_offset + mStart)
{
llerrs << "getLength() < segment_offset + mStart\t getLength()\t" << getLength() << "\tsegment_offset:\t"
<< segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl;
}
if(offsetString.length() + 1 < max_chars)
{
llerrs << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length()
<< getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl;
}
S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(),
(F32)num_pixels, (F32)num_pixels,
max_chars, max_chars,
word_wrap_style); word_wrap_style);

View File

@ -2515,7 +2515,6 @@ void LLTextEditor::updateSegments()
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
clearSegments(); clearSegments();
segment_set_t::iterator insert_it = mSegments.begin();
for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{ {
insertSegment(*list_it); insertSegment(*list_it);

View File

@ -1059,10 +1059,9 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// Convert drag position into insert position and rank // Convert drag position into insert position and rank
if (!isReadOnly() && handled && !drop) if (!isReadOnly() && handled && !drop)
{ {
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; if (cargo_type == DAD_WIDGET)
LLAssetType::EType type = inv_item->getType();
if (type == LLAssetType::AT_WIDGET)
{ {
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
LLCommandId dragged_command(inv_item->getUUID()); LLCommandId dragged_command(inv_item->getUUID());
int orig_rank = getRankFromPosition(dragged_command); int orig_rank = getRankFromPosition(dragged_command);
mDragRank = getRankFromPosition(x, y); mDragRank = getRankFromPosition(x, y);

View File

@ -24,7 +24,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
#include "linden_common.h" #include "linden_common.h"
#include "llurlaction.h" #include "llurlaction.h"
@ -32,6 +31,7 @@
#include "llwindow.h" #include "llwindow.h"
#include "llurlregistry.h" #include "llurlregistry.h"
// global state for the callback functions // global state for the callback functions
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback; LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback; LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
@ -158,16 +158,33 @@ void LLUrlAction::showProfile(std::string url)
} }
} }
void LLUrlAction::sendIM(std::string url) std::string LLUrlAction::getUserID(std::string url)
{ {
LLURI uri(url); LLURI uri(url);
LLSD path_array = uri.pathArray(); LLSD path_array = uri.pathArray();
std::string id_str;
if (path_array.size() == 4) if (path_array.size() == 4)
{ {
std::string id_str = path_array.get(2).asString(); id_str = path_array.get(2).asString();
if (LLUUID::validate(id_str)) }
{ return id_str;
executeSLURL("secondlife:///app/agent/" + id_str + "/im"); }
}
void LLUrlAction::sendIM(std::string url)
{
std::string id_str = getUserID(url);
if (LLUUID::validate(id_str))
{
executeSLURL("secondlife:///app/agent/" + id_str + "/im");
} }
} }
void LLUrlAction::addFriend(std::string url)
{
std::string id_str = getUserID(url);
if (LLUUID::validate(id_str))
{
executeSLURL("secondlife:///app/agent/" + id_str + "/requestfriend");
}
}

View File

@ -76,7 +76,9 @@ public:
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url); static void showProfile(std::string url);
static std::string getUserID(std::string url);
static void sendIM(std::string url); static void sendIM(std::string url);
static void addFriend(std::string url);
/// specify the callbacks to enable this class's functionality /// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t; typedef boost::function<void (const std::string&)> url_callback_t;

View File

@ -1584,6 +1584,28 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>ChatLoadGroupMaxMembers</key>
<map>
<key>Comment</key>
<string>Max number of active members we'll show up for an unresponsive group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>100</real>
</map>
<key>ChatLoadGroupTimeout</key>
<map>
<key>Comment</key>
<string>Time we give the server to send group participants before we hit the server for group info (seconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
</map>
<key>ChatOnlineNotification</key> <key>ChatOnlineNotification</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -1694,17 +1716,6 @@
<key>Value</key> <key>Value</key>
<integer>131073</integer> <integer>131073</integer>
</map> </map>
<key>NearbyChatIsNotTornOff</key>
<map>
<key>Comment</key>
<string>saving torn-off state of the nearby chat between sessions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>CloseChatOnReturn</key> <key>CloseChatOnReturn</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -4259,6 +4270,17 @@
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map>
<key>IMShowContentPanel</key>
<map>
<key>Comment</key>
<string>Show Toolbar and Body Panels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map> </map>
<key>IgnoreAllNotifications</key> <key>IgnoreAllNotifications</key>
<map> <map>

View File

@ -281,6 +281,28 @@
<key>Value</key> <key>Value</key>
<integer>2</integer> <integer>2</integer>
</map> </map>
<key>NearbyChatIsNotTornOff</key>
<map>
<key>Comment</key>
<string>saving torn-off state of the nearby chat between sessions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NearbyChatIsNotCollapsed</key>
<map>
<key>Comment</key>
<string>Saving expanded/collapsed state of the nearby chat between sessions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowFavoritesOnLogin</key> <key>ShowFavoritesOnLogin</key>
<map> <map>
<key>Comment</key> <key>Comment</key>

View File

@ -193,7 +193,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
// static // static
void LLAvatarActions::startIM(const LLUUID& id) void LLAvatarActions::startIM(const LLUUID& id)
{ {
if (id.isNull()) if (id.isNull() || gAgent.getID() == id)
return; return;
LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2)); LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2));

View File

@ -58,7 +58,7 @@
#include "llworld.h" #include "llworld.h"
#include "lluiconstants.h" #include "lluiconstants.h"
#include "llstring.h" #include "llstring.h"
#include "llurlaction.h"
#include "llviewercontrol.h" #include "llviewercontrol.h"
static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
@ -156,6 +156,17 @@ public:
LLFloaterSidePanelContainer::showPanel("people", "panel_people", LLFloaterSidePanelContainer::showPanel("people", "panel_people",
LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));
} }
else if (level == "map")
{
std::string url = "secondlife://" + mObjectData["slurl"].asString();
LLUrlAction::showLocationOnMap(url);
}
else if (level == "teleport")
{
std::string url = "secondlife://" + mObjectData["slurl"].asString();
LLUrlAction::teleportToLocation(url);
}
} }
void onAvatarIconContextMenuItemClicked(const LLSD& userdata) void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
@ -820,6 +831,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
body_message_params.font.style = "ITALIC"; body_message_params.font.style = "ITALIC";
} }
if(chat.mChatType == CHAT_TYPE_WHISPER)
{
body_message_params.font.style = "ITALIC";
}
else if(chat.mChatType == CHAT_TYPE_SHOUT)
{
body_message_params.font.style = "BOLD";
}
bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;
// We graying out chat history by graying out messages that contains full date in a time string // We graying out chat history by graying out messages that contains full date in a time string
if (message_from_log) if (message_from_log)

View File

@ -174,6 +174,7 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
if("close all" == action) if("close all" == action)
{ {
LLNotificationWellWindow::getInstance()->closeAll(); LLNotificationWellWindow::getInstance()->closeAll();
LLIMWellWindow::getInstance()->closeAll();
} }
} }
@ -427,6 +428,8 @@ LLChicletPanel::~LLChicletPanel()
void LLChicletPanel::onMessageCountChanged(const LLSD& data) void LLChicletPanel::onMessageCountChanged(const LLSD& data)
{ {
// *TODO : we either suppress this method or return a value. Right now, it servers no purpose.
/*
LLUUID session_id = data["session_id"].asUUID(); LLUUID session_id = data["session_id"].asUUID();
S32 unread = data["participant_unread"].asInteger(); S32 unread = data["participant_unread"].asInteger();
@ -435,6 +438,7 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data)
{ {
unread = 0; unread = 0;
} }
*/
} }
void LLChicletPanel::objectChicletCallback(const LLSD& data) void LLChicletPanel::objectChicletCallback(const LLSD& data)

View File

@ -28,9 +28,11 @@
#include "llagent.h" #include "llagent.h"
#include "llavatarnamecache.h" #include "llavatarnamecache.h"
#include "llconversationlog.h" #include "llconversationlog.h"
#include "lldiriterator.h"
#include "llnotificationsutil.h" #include "llnotificationsutil.h"
#include "lltrans.h" #include "lltrans.h"
#include <boost/foreach.hpp>
#include "boost/lexical_cast.hpp" #include "boost/lexical_cast.hpp"
const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec
@ -192,14 +194,17 @@ LLConversationLog::LLConversationLog() :
mAvatarNameCacheConnection(), mAvatarNameCacheConnection(),
mLoggingEnabled(false) mLoggingEnabled(false)
{ {
LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get(); if(gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts"))
S32 log_mode = keep_log_ctrlp->getValue();
keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
if (log_mode > 0)
{ {
loadFromFile(getFileName()); LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get();
S32 log_mode = keep_log_ctrlp->getValue();
keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
if (log_mode > 0)
{
loadFromFile(getFileName());
enableLogging(log_mode); enableLogging(log_mode);
}
} }
} }
@ -380,6 +385,36 @@ void LLConversationLog::cache()
} }
} }
void LLConversationLog::getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs)
{
// get Users log directory
std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
// add final OS dependent delimiter
dirname += gDirUtilp->getDirDelimiter();
// create search pattern
std::string pattern = "conversation.log.backup*";
LLDirIterator iter(dirname, pattern);
std::string filename;
while (iter.next(filename))
{
list_of_backup_logs.push_back(gDirUtilp->add(dirname, filename));
}
}
void LLConversationLog::deleteBackupLogs()
{
std::vector<std::string> backup_logs;
getListOfBackupLogs(backup_logs);
BOOST_FOREACH(const std::string& fullpath, backup_logs)
{
LLFile::remove(fullpath);
}
}
bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory) bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory)
{ {
@ -575,5 +610,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD&
mConversations.clear(); mConversations.clear();
notifyObservers(); notifyObservers();
cache(); cache();
deleteBackupLogs();
} }
} }

View File

@ -138,6 +138,8 @@ public:
*/ */
void cache(); void cache();
bool moveLog(const std::string &originDirectory, const std::string &targetDirectory); bool moveLog(const std::string &originDirectory, const std::string &targetDirectory);
void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs);
void deleteBackupLogs();
void onClearLog(); void onClearLog();
void onClearLogResponse(const LLSD& notification, const LLSD& response); void onClearLogResponse(const LLSD& notification, const LLSD& response);

View File

@ -198,6 +198,8 @@ void LLConversationLogList::refresh()
void LLConversationLogList::rebuildList() void LLConversationLogList::rebuildList()
{ {
const LLConversation * selected_conversationp = getSelectedConversation();
clear(); clear();
bool have_filter = !mNameFilter.empty(); bool have_filter = !mNameFilter.empty();
@ -214,7 +216,12 @@ void LLConversationLogList::rebuildList()
addNewItem(&*iter); addNewItem(&*iter);
} }
// try to restore selection of item
if (NULL != selected_conversationp)
{
selectItemByUUID(selected_conversationp->getSessionID());
}
bool logging_enabled = log_instance.getIsLoggingEnabled(); bool logging_enabled = log_instance.getIsLoggingEnabled();
bool log_empty = log_instance.isLogEmpty(); bool log_empty = log_instance.isLogEmpty();
@ -238,8 +245,16 @@ void LLConversationLogList::rebuildList()
void LLConversationLogList::onCustomAction(const LLSD& userdata) void LLConversationLogList::onCustomAction(const LLSD& userdata)
{ {
const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp)
{
return;
}
const std::string command_name = userdata.asString(); const std::string command_name = userdata.asString();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); const LLUUID& selected_conversation_participant_id = selected_conversationp->getParticipantID();
const LLUUID& selected_conversation_session_id = selected_conversationp->getSessionID();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
if ("im" == command_name) if ("im" == command_name)
@ -247,11 +262,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype) switch (stype)
{ {
case LLIMModel::LLIMSession::P2P_SESSION: case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::startIM(selected_id); LLAvatarActions::startIM(selected_conversation_participant_id);
break; break;
case LLIMModel::LLIMSession::GROUP_SESSION: case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::startIM(getSelectedConversation()->getSessionID()); LLGroupActions::startIM(selected_conversation_session_id);
break; break;
default: default:
@ -263,11 +278,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype) switch (stype)
{ {
case LLIMModel::LLIMSession::P2P_SESSION: case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::startCall(selected_id); LLAvatarActions::startCall(selected_conversation_participant_id);
break; break;
case LLIMModel::LLIMSession::GROUP_SESSION: case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::startCall(getSelectedConversation()->getSessionID()); LLGroupActions::startCall(selected_conversation_session_id);
break; break;
default: default:
@ -279,11 +294,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype) switch (stype)
{ {
case LLIMModel::LLIMSession::P2P_SESSION: case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::showProfile(selected_id); LLAvatarActions::showProfile(selected_conversation_participant_id);
break; break;
case LLIMModel::LLIMSession::GROUP_SESSION: case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::show(getSelectedConversation()->getSessionID()); LLGroupActions::show(selected_conversation_session_id);
break; break;
default: default:
@ -292,52 +307,53 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
} }
else if ("chat_history" == command_name) else if ("chat_history" == command_name)
{ {
const LLUUID& session_id = getSelectedConversation()->getSessionID(); LLFloaterReg::showInstance("preview_conversation", selected_conversation_session_id, true);
LLFloaterReg::showInstance("preview_conversation", session_id, true);
} }
else if ("offer_teleport" == command_name) else if ("offer_teleport" == command_name)
{ {
LLAvatarActions::offerTeleport(selected_id); LLAvatarActions::offerTeleport(selected_conversation_participant_id);
} }
else if("add_friend" == command_name) else if("add_friend" == command_name)
{ {
if (!LLAvatarActions::isFriend(selected_id)) if (!LLAvatarActions::isFriend(selected_conversation_participant_id))
{ {
LLAvatarActions::requestFriendshipDialog(selected_id); LLAvatarActions::requestFriendshipDialog(selected_conversation_participant_id);
} }
} }
else if("remove_friend" == command_name) else if("remove_friend" == command_name)
{ {
if (LLAvatarActions::isFriend(selected_id)) if (LLAvatarActions::isFriend(selected_conversation_participant_id))
{ {
LLAvatarActions::removeFriendDialog(selected_id); LLAvatarActions::removeFriendDialog(selected_conversation_participant_id);
} }
} }
else if ("invite_to_group" == command_name) else if ("invite_to_group" == command_name)
{ {
LLAvatarActions::inviteToGroup(selected_id); LLAvatarActions::inviteToGroup(selected_conversation_participant_id);
} }
else if ("show_on_map" == command_name) else if ("show_on_map" == command_name)
{ {
LLAvatarActions::showOnMap(selected_id); LLAvatarActions::showOnMap(selected_conversation_participant_id);
} }
else if ("share" == command_name) else if ("share" == command_name)
{ {
LLAvatarActions::share(selected_id); LLAvatarActions::share(selected_conversation_participant_id);
} }
else if ("pay" == command_name) else if ("pay" == command_name)
{ {
LLAvatarActions::pay(selected_id); LLAvatarActions::pay(selected_conversation_participant_id);
} }
else if ("block" == command_name) else if ("block" == command_name)
{ {
LLAvatarActions::toggleBlock(selected_id); LLAvatarActions::toggleBlock(selected_conversation_participant_id);
} }
} }
bool LLConversationLogList::isActionEnabled(const LLSD& userdata) bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{ {
if (numSelected() != 1) const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp || numSelected() > 1)
{ {
return false; return false;
} }
@ -345,7 +361,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
const std::string command_name = userdata.asString(); const std::string command_name = userdata.asString();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype; bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype;
bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype;
@ -374,7 +390,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{ {
return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); return is_p2p && LLAvatarActions::canOfferTeleport(selected_id);
} }
else if ("can_show_on_map") else if ("can_show_on_map" == command_name)
{ {
return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike());
} }
@ -384,9 +400,16 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
bool LLConversationLogList::isActionChecked(const LLSD& userdata) bool LLConversationLogList::isActionChecked(const LLSD& userdata)
{ {
const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp)
{
return false;
}
const std::string command_name = userdata.asString(); const std::string command_name = userdata.asString();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType();
if ("is_blocked" == command_name) if ("is_blocked" == command_name)

View File

@ -139,6 +139,8 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("remove_friend")); items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group")); items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group")); items.push_back(std::string("separator_invite_to_group"));
if (static_cast<LLConversationItem*>(mParent)->getType() == CONV_SESSION_NEARBY)
items.push_back(std::string("zoom_in"));
items.push_back(std::string("map")); items.push_back(std::string("map"));
items.push_back(std::string("share")); items.push_back(std::string("share"));
items.push_back(std::string("pay")); items.push_back(std::string("pay"));

View File

@ -104,6 +104,15 @@ LLConversationViewSession::~LLConversationViewSession()
void LLConversationViewSession::setFlashState(bool flash_state) void LLConversationViewSession::setFlashState(bool flash_state)
{ {
if (flash_state && !mFlashStateOn)
{
// flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
if (mContainer->isScrolledOutOfSight(this))
{
gToolBarView->flashCommand(LLCommandId("chat"), true);
}
}
mFlashStateOn = flash_state; mFlashStateOn = flash_state;
mFlashStarted = false; mFlashStarted = false;
mFlashTimer->stopFlashing(); mFlashTimer->stopFlashing();
@ -115,12 +124,6 @@ void LLConversationViewSession::startFlashing()
{ {
mFlashStarted = true; mFlashStarted = true;
mFlashTimer->startFlashing(); mFlashTimer->startFlashing();
// flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
if (mContainer->isScrolledOutOfSight(this))
{
gToolBarView->flashCommand(LLCommandId("chat"), true);
}
} }
} }
@ -254,20 +257,38 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )
//This node (conversation) was selected and a child (participant) was not //This node (conversation) was selected and a child (participant) was not
if(result && getRoot()) if(result && getRoot())
{ {
if(getRoot()->getCurSelectedItem() == this) selectConversationItem();
{
LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
LLUUID session_id = item? item->getUUID() : LLUUID();
LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
im_container->flashConversationItemWidget(session_id,false);
im_container->selectConversationPair(session_id, false);
im_container->collapseMessagesPane(false);
}
} }
return result; return result;
} }
BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask )
{
BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask);
if(result)
{
selectConversationItem();
}
return result;
}
void LLConversationViewSession::selectConversationItem()
{
if(getRoot()->getCurSelectedItem() == this)
{
LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
LLUUID session_id = item? item->getUUID() : LLUUID();
LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
im_container->flashConversationItemWidget(session_id,false);
im_container->selectConversationPair(session_id, false);
im_container->collapseMessagesPane(false);
}
}
// virtual // virtual
S32 LLConversationViewSession::arrange(S32* width, S32* height) S32 LLConversationViewSession::arrange(S32* width, S32* height)
{ {

View File

@ -68,6 +68,7 @@ public:
/*virtual*/ BOOL postBuild(); /*virtual*/ BOOL postBuild();
/*virtual*/ void draw(); /*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ S32 arrange(S32* width, S32* height); /*virtual*/ S32 arrange(S32* width, S32* height);
@ -90,6 +91,7 @@ private:
void onCurrentVoiceSessionChanged(const LLUUID& session_id); void onCurrentVoiceSessionChanged(const LLUUID& session_id);
void startFlashing(); void startFlashing();
void selectConversationItem();
LLPanel* mItemPanel; LLPanel* mItemPanel;
LLPanel* mCallIconLayoutPanel; LLPanel* mCallIconLayoutPanel;

View File

@ -113,9 +113,11 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
} }
} }
if(!LLApp::isQuitting())
LLNotificationsUtil::add(ent.mNotifyName, args); {
LLNotificationsUtil::add(ent.mNotifyName, args);
}
return true; return true;
} }

View File

@ -33,6 +33,7 @@
#include "lldir.h" #include "lldir.h"
#include "llerror.h" #include "llerror.h"
#include "llfloaterreg.h" #include "llfloaterreg.h"
#include "llimview.h"
#include "llnotifications.h" #include "llnotifications.h"
#include "llnotificationhandler.h" #include "llnotificationhandler.h"
#include "llnotificationstorage.h" #include "llnotificationstorage.h"
@ -131,6 +132,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
{ {
LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS); LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);
LL_INFOS("LLDoNotDisturbNotificationStorage") << "start loading notifications" << LL_ENDL;
LLSD input; LLSD input;
if (!readNotifications(input) ||input.isUndefined()) if (!readNotifications(input) ||input.isUndefined())
{ {
@ -145,6 +148,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLNotifications& instance = LLNotifications::instance(); LLNotifications& instance = LLNotifications::instance();
bool imToastExists = false; bool imToastExists = false;
bool group_ad_hoc_toast_exists = false;
S32 toastSessionType;
bool offerExists = false; bool offerExists = false;
for (LLSD::array_const_iterator notification_it = data.beginArray(); for (LLSD::array_const_iterator notification_it = data.beginArray();
@ -158,7 +163,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
if(notificationName == toastName) if(notificationName == toastName)
{ {
imToastExists = true; toastSessionType = notification_params["payload"]["SESSION_TYPE"];
if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION)
{
imToastExists = true;
}
//Don't add group/ad-hoc messages to the notification system because
//this means the group/ad-hoc session has to be re-created
else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION
|| toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION)
{
//Just allows opening the conversation log for group/ad-hoc messages upon startup
group_ad_hoc_toast_exists = true;
continue;
}
} }
else if(notificationName == offerName) else if(notificationName == offerName)
{ {
@ -197,13 +215,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLFloaterReg::showInstance("im_container"); LLFloaterReg::showInstance("im_container");
} }
if(imToastExists || offerExists) if(group_ad_hoc_toast_exists)
{
LLFloaterReg::showInstance("conversation");
}
if(imToastExists || group_ad_hoc_toast_exists || offerExists)
{ {
make_ui_sound_deferred("UISndNewIncomingIMSession"); make_ui_sound_deferred("UISndNewIncomingIMSession");
} }
//writes out empty .xml file (since LLCommunicationChannel::mHistory is empty) //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty)
saveNotifications(); saveNotifications();
LL_INFOS("LLDoNotDisturbNotificationStorage") << "finished loading notifications" << LL_ENDL;
} }
void LLDoNotDisturbNotificationStorage::updateNotifications() void LLDoNotDisturbNotificationStorage::updateNotifications()

View File

@ -53,6 +53,7 @@
#include "llcallbacklist.h" #include "llcallbacklist.h"
#include "llworld.h" #include "llworld.h"
#include "llsdserialize.h" #include "llsdserialize.h"
#include "llviewerobjectlist.h"
// //
// LLFloaterIMContainer // LLFloaterIMContainer
@ -62,8 +63,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL), mExpandCollapseBtn(NULL),
mConversationsRoot(NULL), mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"), mConversationsEventStream("ConversationsEvents"),
mInitialized(false), mInitialized(false)
mIsFirstLaunch(false)
{ {
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2)); mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@ -114,6 +114,7 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str
void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{ {
selectConversationPair(session_id, true); selectConversationPair(session_id, true);
collapseMessagesPane(false);
} }
void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)
@ -225,10 +226,11 @@ BOOL LLFloaterIMContainer::postBuild()
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false);
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false));
mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this));
if (! mMessagesPane->isCollapsed())
if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed())
{ {
S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth");
LLRect conversations_panel_rect = mConversationsPane->getRect(); LLRect conversations_panel_rect = mConversationsPane->getRect();
@ -243,7 +245,6 @@ BOOL LLFloaterIMContainer::postBuild()
mGeneralTitle = getTitle(); mGeneralTitle = getTitle();
mInitialized = true; mInitialized = true;
mIsFirstLaunch = true;
// Add callbacks: // Add callbacks:
// We'll take care of view updates on idle // We'll take care of view updates on idle
@ -278,12 +279,6 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLUUID session_id = floaterp->getKey(); LLUUID session_id = floaterp->getKey();
// Make sure the message panel is open when adding a floater or it stays mysteriously hidden
if (!mIsFirstLaunch)
{
collapseMessagesPane(false);
}
// Add the floater // Add the floater
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
@ -631,6 +626,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLMultiFloater::setVisible(visible); LLMultiFloater::setVisible(visible);
} }
void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
selectConversationPair(getSelectedSession(), false, take_focus);
}
void LLFloaterIMContainer::updateResizeLimits() void LLFloaterIMContainer::updateResizeLimits()
{ {
LLMultiFloater::updateResizeLimits(); LLMultiFloater::updateResizeLimits();
@ -644,8 +645,6 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
return; return;
} }
mIsFirstLaunch = false;
// Save current width of panels before collapsing/expanding right pane. // Save current width of panels before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth(); S32 conv_pane_width = mConversationsPane->getRect().getWidth();
S32 msg_pane_width = mMessagesPane->getRect().getWidth(); S32 msg_pane_width = mMessagesPane->getRect().getWidth();
@ -667,7 +666,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
// Make sure layout is updated before resizing conversation pane. // Make sure layout is updated before resizing conversation pane.
mConversationsStack->updateLayout(); mConversationsStack->updateLayout();
updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); reshapeFloaterAndSetResizeLimits(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
if (!collapse) if (!collapse)
{ {
@ -676,7 +675,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
} }
} }
void LLFloaterIMContainer::collapseConversationsPane(bool collapse) void LLFloaterIMContainer::collapseConversationsPane(bool collapse, bool save_is_allowed /*=true*/)
{ {
if (mConversationsPane->isCollapsed() == collapse) if (mConversationsPane->isCollapsed() == collapse)
{ {
@ -690,7 +689,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
// Save current width of Conversation panel before collapsing/expanding right pane. // Save current width of Conversation panel before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth(); S32 conv_pane_width = mConversationsPane->getRect().getWidth();
if (collapse) if (collapse && save_is_allowed)
{ {
// Save the conversations pane width before collapsing it. // Save the conversations pane width before collapsing it.
gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width);
@ -700,10 +699,18 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
} }
mConversationsStack->collapsePanel(mConversationsPane, collapse); mConversationsStack->collapsePanel(mConversationsPane, collapse);
if (!collapse)
{
// Make sure layout is updated before resizing conversation pane.
mConversationsStack->updateLayout();
// Restore conversation's pane previous width.
mConversationsPane->setTargetDim(gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"));
}
S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); S32 delta_width =
gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim();
updateState(collapse, delta_width); reshapeFloaterAndSetResizeLimits(collapse, delta_width);
for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
widget_it != mConversationsWidgets.end(); ++widget_it) widget_it != mConversationsWidgets.end(); ++widget_it)
@ -723,21 +730,20 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
} }
} }
void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width)
{ {
LLRect floater_rect = getRect(); LLRect floater_rect = getRect();
floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width);
// Set by_user = true so that reshaped rect is saved in user_settings. // Set by_user = true so that reshaped rect is saved in user_settings.
setShape(floater_rect, true); setShape(floater_rect, true);
updateResizeLimits(); updateResizeLimits();
bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); bool at_least_one_panel_is_expanded =
bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); ! (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed());
setCanResize(is_left_pane_expanded || is_right_pane_expanded); setCanResize(at_least_one_panel_is_expanded);
setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits(); assignResizeLimits();
@ -758,21 +764,17 @@ void LLFloaterIMContainer::assignResizeLimits()
// between the panels are merged into one // between the panels are merged into one
S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);
S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;
S32 conv_pane_current_width = is_msg_pane_expanded S32 conv_pane_target_width = is_conv_pane_expanded?
? (is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim()) (is_msg_pane_expanded?
: (is_conv_pane_expanded? mConversationsPane->getExpandedMinDim() : mConversationsPane->getMinDim()); mConversationsPane->getRect().getWidth()
: mConversationsPane->getExpandedMinDim())
: mConversationsPane->getMinDim();
S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;
S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders;
if (is_conv_pane_expanded)
{
// Save the conversations pane width.
gSavedPerAccountSettings.setS32(
"ConversationsListPaneWidth",
mConversationsPane->getRect().getWidth());
}
setResizeLimits(new_min_width, getMinHeight()); setResizeLimits(new_min_width, getMinHeight());
mConversationsStack->updateLayout();
} }
void LLFloaterIMContainer::onAddButtonClicked() void LLFloaterIMContainer::onAddButtonClicked()
@ -1031,6 +1033,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
{ {
LLAvatarActions::inviteToGroup(userID); LLAvatarActions::inviteToGroup(userID);
} }
else if ("zoom_in" == command)
{
handle_zoom_to_object(userID);
}
else if ("map" == command) else if ("map" == command)
{ {
LLAvatarActions::showOnMap(userID); LLAvatarActions::showOnMap(userID);
@ -1252,6 +1258,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{ {
return LLAvatarActions::canCall(); return LLAvatarActions::canCall();
} }
else if ("can_zoom_in" == item)
{
return is_single_select && gObjectList.findObject(single_id);
}
else if ("can_show_on_map" == item) else if ("can_show_on_map" == item)
{ {
return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false); return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false);
@ -1325,6 +1335,12 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
{ {
setVisibleAndFrontmost(false); setVisibleAndFrontmost(false);
selectConversationPair(session_id, true); selectConversationPair(session_id, true);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
if (session_floater)
{
session_floater->restoreFloater();
}
} }
void LLFloaterIMContainer::clearAllFlashStates() void LLFloaterIMContainer::clearAllFlashStates()
@ -1400,6 +1416,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
// Switch to the conversation floater that is being selected // Switch to the conversation floater that is being selected
selectFloater(session_floater); selectFloater(session_floater);
} }
else
{
showStub(true);
}
} }
// Set the focus on the selected floater // Set the focus on the selected floater
@ -1410,7 +1430,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
session_floater->setMinimized(is_minimized); session_floater->setMinimized(is_minimized);
} }
} }
flashConversationItemWidget(session_id,false);
return handled; return handled;
} }
@ -1878,6 +1898,9 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
{ {
llassert(conversation_item_widget != NULL); llassert(conversation_item_widget != NULL);
// make sure the widget is actually in the right spot first
mConversationsRoot->arrange(NULL, NULL);
// check whether the widget is in the visible portion of the scroll container // check whether the widget is in the visible portion of the scroll container
LLRect widget_rect; LLRect widget_rect;
conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot); conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot);
@ -1905,7 +1928,19 @@ BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
return TRUE; return TRUE;
} }
bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next) bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
{
bool selectedAdjacentConversation = selectNextorPreviousConversation(true, focus_selected);
if(!selectedAdjacentConversation)
{
selectedAdjacentConversation = selectNextorPreviousConversation(false, focus_selected);
}
return selectedAdjacentConversation;
}
bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next, bool focus_selected)
{ {
if (mConversationsWidgets.size() > 1) if (mConversationsWidgets.size() > 1)
{ {
@ -1926,12 +1961,7 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem()); LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
if (vmi) if (vmi)
{ {
selectConversationPair(vmi->getUUID(), true); selectConversationPair(vmi->getUUID(), true, focus_selected);
LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession());
if(floaterp && !floaterp->isTornOff())
{
setFocus(TRUE);
}
return true; return true;
} }
} }
@ -1942,10 +1972,13 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
void LLFloaterIMContainer::expandConversation() void LLFloaterIMContainer::expandConversation()
{ {
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession())); if(!mConversationsPane->isCollapsed())
if (widget)
{ {
widget->setOpen(!widget->isOpen()); LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession()));
if (widget)
{
widget->setOpen(!widget->isOpen());
}
} }
} }
@ -1955,11 +1988,6 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
// Most of the time the user will never see this state. // Most of the time the user will never see this state.
setMinimized(FALSE); setMinimized(FALSE);
// Save the conversations pane width.
gSavedPerAccountSettings.setS32(
"ConversationsListPaneWidth",
mConversationsPane->getRect().getWidth());
LLFloater::closeFloater(app_quitting); LLFloater::closeFloater(app_quitting);
} }

View File

@ -60,6 +60,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void draw(); /*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible); /*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void updateResizeLimits(); /*virtual*/ void updateResizeLimits();
void onCloseFloater(LLUUID& id); void onCloseFloater(LLUUID& id);
@ -72,7 +73,8 @@ public:
void selectNextConversationByID(const LLUUID& session_id); void selectNextConversationByID(const LLUUID& session_id);
BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true);
void clearAllFlashStates(); void clearAllFlashStates();
bool selectNextorPreviousConversation(bool select_next); bool selectAdjacentConversation(bool focus_selected);
bool selectNextorPreviousConversation(bool select_next, bool focus_selected = true);
void expandConversation(); void expandConversation();
/*virtual*/ void tabClose(); /*virtual*/ void tabClose();
@ -128,9 +130,9 @@ private:
void processParticipantsStyleUpdate(); void processParticipantsStyleUpdate();
void onSpeakButtonClicked(); void onSpeakButtonClicked();
void collapseConversationsPane(bool collapse); void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
void updateState(bool collapse, S32 delta_width); void reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width);
void onAddButtonClicked(); void onAddButtonClicked();
void onAvatarPicked(const uuid_vec_t& ids); void onAvatarPicked(const uuid_vec_t& ids);
@ -173,7 +175,6 @@ private:
LLLayoutStack* mConversationsStack; LLLayoutStack* mConversationsStack;
bool mInitialized; bool mInitialized;
bool mIsFirstLaunch;
LLUUID mSelectedSession; LLUUID mSelectedSession;
std::string mGeneralTitle; std::string mGeneralTitle;

View File

@ -257,14 +257,25 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible)
} }
} }
void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key);
if(!isTornOff() && matchesKey(key))
{
LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, false);
}
}
// virtual // virtual
void LLFloaterIMNearbyChat::onTearOffClicked() void LLFloaterIMNearbyChat::onTearOffClicked()
{ {
LLFloaterIMSessionTab::onTearOffClicked(); LLFloaterIMSessionTab::onTearOffClicked();
// see CHUI-170: Save torn-off state of the nearby chat between sessions // see CHUI-170: Save torn-off state of the nearby chat between sessions
BOOL in_the_multifloater = !isTornOff(); BOOL in_the_multifloater = (BOOL)getHost();
gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); gSavedPerAccountSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater);
} }
@ -272,6 +283,11 @@ void LLFloaterIMNearbyChat::onTearOffClicked()
void LLFloaterIMNearbyChat::onOpen(const LLSD& key) void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
{ {
LLFloaterIMSessionTab::onOpen(key); LLFloaterIMSessionTab::onOpen(key);
if(!isMessagePaneExpanded())
{
restoreFloater();
onCollapseToLine(this);
}
showTranslationCheckbox(LLTranslate::isTranslationConfigured()); showTranslationCheckbox(LLTranslate::isTranslationConfigured());
} }
@ -279,6 +295,7 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
void LLFloaterIMNearbyChat::onClose(bool app_quitting) void LLFloaterIMNearbyChat::onClose(bool app_quitting)
{ {
// Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater // Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater
LLFloaterIMSessionTab::restoreFloater();
onClickCloseBtn(); onClickCloseBtn();
} }
@ -286,8 +303,10 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)
void LLFloaterIMNearbyChat::onClickCloseBtn() void LLFloaterIMNearbyChat::onClickCloseBtn()
{ {
if (!isTornOff()) if (!isTornOff())
{
return; return;
onTearOffClicked(); }
LLFloaterIMSessionTab::onTearOffClicked();
LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance(); LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance();
if (im_box) if (im_box)
@ -308,11 +327,8 @@ void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp)
void LLFloaterIMNearbyChat::show() void LLFloaterIMNearbyChat::show()
{ {
if (isChatMultiTab())
{
openFloater(getKey()); openFloater(getKey());
} }
}
bool LLFloaterIMNearbyChat::isChatVisible() const bool LLFloaterIMNearbyChat::isChatVisible() const
{ {
@ -323,7 +339,7 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
if (im_box != NULL) if (im_box != NULL)
{ {
isVisible = isVisible =
isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? isChatMultiTab() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff")?
im_box->getVisible() && !im_box->isMinimized() : im_box->getVisible() && !im_box->isMinimized() :
getVisible() && !isMinimized(); getVisible() && !isMinimized();
} }
@ -334,6 +350,11 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
void LLFloaterIMNearbyChat::showHistory() void LLFloaterIMNearbyChat::showHistory()
{ {
openFloater(); openFloater();
if(!isMessagePaneExpanded())
{
restoreFloater();
setFocus(true);
}
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
} }
@ -406,6 +427,12 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std:
void LLFloaterIMNearbyChat::onChatBoxKeystroke() void LLFloaterIMNearbyChat::onChatBoxKeystroke()
{ {
LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
if (im_box)
{
im_box->flashConversationItemWidget(mSessionID,false);
}
LLFirstUse::otherAvatarChatFirst(false); LLFirstUse::otherAvatarChatFirst(false);
LLWString raw_text = mInputEditor->getWText(); LLWString raw_text = mInputEditor->getWText();
@ -455,11 +482,14 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
{ {
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part if (!rest_of_match.empty())
{
mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
// Select to end of line, starting from the character // Select to end of line, starting from the character
// after the last one the user typed. // after the last one the user typed.
mInputEditor->selectNext(rest_of_match, false); mInputEditor->selectNext(rest_of_match, false);
}
} }
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
{ {
@ -714,10 +744,16 @@ void LLFloaterIMNearbyChat::startChat(const char* line)
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (nearby_chat) if (nearby_chat)
{ {
if(!nearby_chat->isTornOff())
{
LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL));
}
if(nearby_chat->isMinimized())
{
nearby_chat->setMinimized(false);
}
nearby_chat->show(); nearby_chat->show();
nearby_chat->setVisible(TRUE);
nearby_chat->setFocus(TRUE); nearby_chat->setFocus(TRUE);
nearby_chat->mInputEditor->setFocus(TRUE);
if (line) if (line)
{ {

View File

@ -54,6 +54,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting); /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void setVisible(BOOL visible); /*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void closeHostedFloater(); /*virtual*/ void closeHostedFloater();
void loadHistory(); void loadHistory();

View File

@ -559,12 +559,12 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
if( nearby_chat->hasFocus() if(( ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
|| im_box->hasFocus()
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
&& gSavedSettings.getBOOL("UseChatBubbles") ) && gSavedSettings.getBOOL("UseChatBubbles") )
|| mChannel.isDead() || mChannel.isDead()
|| !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode || !mChannel.get()->getShowToasts() )
&& nearby_chat->isMessagePaneExpanded())
// to prevent toasts in Do Not Disturb mode
return;//no need in toast if chat is visible or if bubble chat is enabled return;//no need in toast if chat is visible or if bubble chat is enabled
// arrange a channel on a screen // arrange a channel on a screen
@ -604,17 +604,16 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
toast_msg = chat_msg.mText; toast_msg = chat_msg.mText;
} }
//Don't show nearby toast, if conversation is visible but not focused //Don't show nearby toast, if conversation is visible and selected
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID()); if (im_box->getSelectedSession().isNull() &&
if (session_floater ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
&& session_floater->isInVisibleChain() && !session_floater->isMinimized() || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized()))
{ {
return; return;
} }
//Will show toast when chat preference is set //Will show toast when chat preference is set
if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !nearby_chat->isMessagePaneExpanded())
{ {
// Add a nearby chat toast. // Add a nearby chat toast.
LLUUID id; LLUUID id;

View File

@ -618,7 +618,9 @@ void LLFloaterIMSession::onClose(bool app_quitting)
// Last change: // Last change:
// EXT-3516 X Button should end IM session, _ button should hide // EXT-3516 X Button should end IM session, _ button should hide
gIMMgr->leaveSession(mSessionID); gIMMgr->leaveSession(mSessionID);
// *TODO: Study why we need to restore the floater before we close it.
// Might be because we want to save some state data in some clean open state.
LLFloaterIMSessionTab::restoreFloater();
// Clean up the conversation *after* the session has been ended // Clean up the conversation *after* the session has been ended
LLFloaterIMSessionTab::onClose(app_quitting); LLFloaterIMSessionTab::onClose(app_quitting);
} }
@ -892,6 +894,11 @@ void LLFloaterIMSession::onInputEditorFocusLost(LLFocusableElement* caller, void
void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata) void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)
{ {
LLFloaterIMSession* self = (LLFloaterIMSession*)userdata; LLFloaterIMSession* self = (LLFloaterIMSession*)userdata;
LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
if (im_box)
{
im_box->flashConversationItemWidget(self->mSessionID,false);
}
std::string text = self->mInputEditor->getText(); std::string text = self->mInputEditor->getText();
// Deleting all text counts as stopping typing. // Deleting all text counts as stopping typing.

View File

@ -30,6 +30,7 @@
#include "llfloaterimsessiontab.h" #include "llfloaterimsessiontab.h"
#include "llagent.h" #include "llagent.h"
#include "llagentcamera.h"
#include "llavataractions.h" #include "llavataractions.h"
#include "llchatentry.h" #include "llchatentry.h"
#include "llchathistory.h" #include "llchathistory.h"
@ -57,10 +58,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mSpeakingIndicator(NULL) , mSpeakingIndicator(NULL)
, mChatHistory(NULL) , mChatHistory(NULL)
, mInputEditor(NULL) , mInputEditor(NULL)
, mInputEditorTopPad(0) , mInputEditorPad(0)
, mRefreshTimer(new LLTimer()) , mRefreshTimer(new LLTimer())
, mIsHostAttached(false) , mIsHostAttached(false)
, mHasVisibleBeenInitialized(false) , mHasVisibleBeenInitialized(false)
, mIsParticipantListExpanded(true)
, mChatLayoutPanel(NULL)
{ {
setAutoFocus(FALSE); setAutoFocus(FALSE);
mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
@ -124,8 +127,18 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible)
if(visible && !mHasVisibleBeenInitialized) if(visible && !mHasVisibleBeenInitialized)
{ {
mHasVisibleBeenInitialized = true; mHasVisibleBeenInitialized = true;
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true); if(!gAgentCamera.cameraMouselook())
{
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
}
LLFloaterIMSessionTab::addToHost(mSessionID); LLFloaterIMSessionTab::addToHost(mSessionID);
LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
if (conversp && conversp->isNearbyChat() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotCollapsed"))
{
onCollapseToLine(this);
}
mInputButtonPanel->setVisible(isTornOff());
} }
LLTransientDockableFloater::setVisible(visible); LLTransientDockableFloater::setVisible(visible);
@ -169,7 +182,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
conversp->setHostAttached(true); conversp->setHostAttached(true);
if (!conversp->isNearbyChat() if (!conversp->isNearbyChat()
|| gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) || gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff"))
{ {
floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT); floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT);
} }
@ -180,6 +193,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
// LLFloater::mLastHostHandle = floater_container (a "future" host) // LLFloater::mLastHostHandle = floater_container (a "future" host)
conversp->setHost(floater_container); conversp->setHost(floater_container);
conversp->setHost(NULL); conversp->setHost(NULL);
conversp->forceReshape(); conversp->forceReshape();
} }
// Added floaters share some state (like sort order) with their host // Added floaters share some state (like sort order) with their host
@ -188,23 +202,51 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
} }
} }
void LLFloaterIMSessionTab::assignResizeLimits()
{
bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed();
// disable a layoutstack's functionality when participant list panel is collapsed
mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
S32 participants_pane_target_width = is_participants_pane_collapsed?
0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH);
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
setResizeLimits(new_min_width, getMinHeight());
this->mParticipantListAndHistoryStack->updateLayout();
}
BOOL LLFloaterIMSessionTab::postBuild() BOOL LLFloaterIMSessionTab::postBuild()
{ {
BOOL result; BOOL result;
mBodyStack = getChild<LLLayoutStack>("main_stack");
mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels");
mCloseBtn = getChild<LLButton>("close_btn"); mCloseBtn = getChild<LLButton>("close_btn");
mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this)); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this));
mExpandCollapseLineBtn = getChild<LLButton>("minz_btn");
mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this));
mTearOffBtn = getChild<LLButton>("tear_off_btn"); mTearOffBtn = getChild<LLButton>("tear_off_btn");
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn"); mGearBtn = getChild<LLButton>("gear_btn");
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
mToolbarPanel = getChild<LLLayoutPanel>("toolbar_panel");
mContentPanel = getChild<LLLayoutPanel>("body_panel");
mInputButtonPanel = getChild<LLLayoutPanel>("input_button_layout_panel");
mInputButtonPanel->setVisible(false);
// Add a scroller for the folder (participant) view // Add a scroller for the folder (participant) view
LLRect scroller_view_rect = mParticipantListPanel->getRect(); LLRect scroller_view_rect = mParticipantListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
@ -221,17 +263,20 @@ BOOL LLFloaterIMSessionTab::postBuild()
mChatHistory = getChild<LLChatHistory>("chat_history"); mChatHistory = getChild<LLChatHistory>("chat_history");
mInputEditor = getChild<LLChatEntry>("chat_editor"); mInputEditor = getChild<LLChatEntry>("chat_editor");
mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatHistory, this));
mChatLayoutPanel = getChild<LLLayoutPanel>("chat_layout_panel");
mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this));
mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setCommitOnFocusLost( FALSE );
mInputEditor->setPassDelete(TRUE); mInputEditor->setPassDelete(TRUE);
mInputEditor->setFont(LLViewerChat::getChatFont()); mInputEditor->setFont(LLViewerChat::getChatFont());
mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; mInputEditorPad = mChatLayoutPanel->getRect().getHeight() - mInputEditor->getRect().getHeight();
setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
mSaveRect = isNearbyChat() mSaveRect = isNearbyChat()
&& !gSavedSettings.getBOOL("NearbyChatIsNotTornOff"); && !gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff");
initRectControl(); initRectControl();
if (isChatMultiTab()) if (isChatMultiTab())
@ -253,6 +298,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
p.root = NULL; p.root = NULL;
p.use_ellipses = true; p.use_ellipses = true;
p.options_menu = "menu_conversation.xml"; p.options_menu = "menu_conversation.xml";
p.name = "root";
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
// Attach that root to the scroller // Attach that root to the scroller
@ -261,6 +307,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
mConversationsRoot->setFollowsAll(); mConversationsRoot->setFollowsAll();
mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
setMessagePaneExpanded(true);
buildConversationViewParticipant(); buildConversationViewParticipant();
refreshConversation(); refreshConversation();
@ -268,6 +316,21 @@ BOOL LLFloaterIMSessionTab::postBuild()
mRefreshTimer->setTimerExpirySec(0); mRefreshTimer->setTimerExpirySec(0);
mRefreshTimer->start(); mRefreshTimer->start();
initBtns(); initBtns();
if (mIsParticipantListExpanded != (bool)gSavedSettings.getBOOL("IMShowControlPanel"))
{
LLFloaterIMSessionTab::onSlide(this);
}
// The resize limits for LLFloaterIMSessionTab should be updated, based on current values of width of conversation and message panels
mParticipantListPanel->getResizeBar()->setResizeListener(boost::bind(&LLFloaterIMSessionTab::assignResizeLimits, this));
mFloaterExtraWidth =
getRect().getWidth()
- mParticipantListAndHistoryStack->getRect().getWidth()
- (mParticipantListPanel->isCollapsed()? 0 : LLPANEL_BORDER_WIDTH);
assignResizeLimits();
return result; return result;
} }
@ -299,7 +362,7 @@ void LLFloaterIMSessionTab::draw()
// Restart the refresh timer // Restart the refresh timer
mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
} }
LLTransientDockableFloater::draw(); LLTransientDockableFloater::draw();
} }
@ -324,13 +387,6 @@ void LLFloaterIMSessionTab::onFocusReceived()
} }
LLTransientDockableFloater::onFocusReceived(); LLTransientDockableFloater::onFocusReceived();
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
if (container)
{
container->selectConversationPair(mSessionID, true);
container->showStub(! getHost());
}
} }
void LLFloaterIMSessionTab::onFocusLost() void LLFloaterIMSessionTab::onFocusLost()
@ -644,14 +700,16 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
// Participant list should be visible only in torn off floaters. // Participant list should be visible only in torn off floaters.
bool is_participant_list_visible = bool is_participant_list_visible =
!is_not_torn_off !is_not_torn_off
&& gSavedSettings.getBOOL("IMShowControlPanel") && mIsParticipantListExpanded
&& !mIsP2PChat; && !mIsP2PChat;
mParticipantListPanel->setVisible(is_participant_list_visible); mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible);
mParticipantListPanel->setVisible(is_participant_list_visible);
// Display collapse image (<<) if the floater is hosted // Display collapse image (<<) if the floater is hosted
// or if it is torn off but has an open control panel. // or if it is torn off but has an open control panel.
bool is_expanded = is_not_torn_off || is_participant_list_visible; bool is_expanded = is_not_torn_off || is_participant_list_visible;
mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
mExpandCollapseBtn->setToolTip( mExpandCollapseBtn->setToolTip(
is_not_torn_off? is_not_torn_off?
@ -672,6 +730,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon")); mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon"));
mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window"));
mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat); mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat);
enableDisableCallBtn(); enableDisableCallBtn();
@ -688,15 +747,11 @@ void LLFloaterIMSessionTab::forceReshape()
} }
void LLFloaterIMSessionTab::reshapeChatHistory() void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
{ {
LLRect chat_rect = mChatHistory->getRect(); LLRect chat_layout_panel_rect = mChatLayoutPanel->getRect();
LLRect input_rect = mInputEditor->getRect(); LLRect input_rect = mInputEditor->getRect();
mChatLayoutPanel->reshape(chat_layout_panel_rect.getWidth(), input_rect.getHeight() + mInputEditorPad, FALSE);
int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad);
chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height);
mChatHistory->setShape(chat_rect);
} }
void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
@ -771,16 +826,77 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
{ {
if (!self->mIsP2PChat) if (!self->mIsP2PChat)
{ {
bool expand = !self->mParticipantListPanel->getVisible(); // The state must toggle the collapsed state of the panel
bool should_be_expanded = self->mParticipantListPanel->isCollapsed();
// Expand/collapse the IM control panel // Update the expand/collapse flag of the participant list panel and save it
self->mParticipantListPanel->setVisible(expand); gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded);
self->mIsParticipantListExpanded = should_be_expanded;
gSavedSettings.setBOOL("IMShowControlPanel", expand);
// Refresh for immediate feedback
self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); self->refreshConversation();
} }
} }
self->assignResizeLimits();
}
void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self)
{
LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost());
if (!host_floater)
{
bool expand = self->isMessagePaneExpanded();
self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon"));
self->mContentPanel->setVisible(!expand);
self->mToolbarPanel->setVisible(!expand);
self->reshapeFloater(expand);
self->setMessagePaneExpanded(!expand);
}
}
void LLFloaterIMSessionTab::reshapeFloater(bool collapse)
{
LLRect floater_rect = getRect();
if(collapse)
{
mFloaterHeight = floater_rect.getHeight();
S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight();
floater_rect.mTop -= height;
enableResizeCtrls(true, true, false);
}
else
{
floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
enableResizeCtrls(true, true, true);
}
saveCollapsedState();
setShape(floater_rect, true);
mBodyStack->updateLayout();
}
void LLFloaterIMSessionTab::restoreFloater()
{
if(!isMessagePaneExpanded())
{
if(isMinimized())
{
setMinimized(false);
}
mContentPanel->setVisible(true);
mToolbarPanel->setVisible(true);
LLRect floater_rect = getRect();
floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
setShape(floater_rect, true);
mBodyStack->updateLayout();
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
setMessagePaneExpanded(true);
saveCollapsedState();
enableResizeCtrls(true, true, true);
}
} }
/*virtual*/ /*virtual*/
@ -792,19 +908,33 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
// Show the messages pane when opening a floater hosted in the Conversations // Show the messages pane when opening a floater hosted in the Conversations
host_floater->collapseMessagesPane(false); host_floater->collapseMessagesPane(false);
} }
mInputButtonPanel->setVisible(isTornOff());
} }
void LLFloaterIMSessionTab::onTearOffClicked() void LLFloaterIMSessionTab::onTearOffClicked()
{ {
setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); restoreFloater();
setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
mSaveRect = isTornOff(); mSaveRect = isTornOff();
initRectControl(); initRectControl();
LLFloater::onClickTearOff(this); LLFloater::onClickTearOff(this);
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
if (isTornOff()) if (isTornOff())
{ {
container->selectAdjacentConversation(false);
forceReshape(); forceReshape();
} }
//Upon re-docking the torn off floater, select the corresponding conversation line item
else
{
container->selectConversation(mSessionID);
}
mInputButtonPanel->setVisible(isTornOff());
refreshConversation(); refreshConversation();
updateGearBtn(); updateGearBtn();
} }
@ -940,6 +1070,14 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()
return conversationItem; return conversationItem;
} }
void LLFloaterIMSessionTab::saveCollapsedState()
{
LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
if(conversp->isNearbyChat())
{
gSavedPerAccountSettings.setBOOL("NearbyChatIsNotCollapsed", isMessagePaneExpanded());
}
}
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{ {
if(mask == MASK_ALT) if(mask == MASK_ALT)

View File

@ -98,6 +98,10 @@ public:
LLConversationItem* getCurSelectedViewModelItem(); LLConversationItem* getCurSelectedViewModelItem();
void forceReshape(); void forceReshape();
virtual BOOL handleKeyHere( KEY key, MASK mask ); virtual BOOL handleKeyHere( KEY key, MASK mask );
bool isMessagePaneExpanded(){return mMessagePaneExpanded;}
void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;}
void restoreFloater();
void saveCollapsedState();
protected: protected:
@ -111,6 +115,8 @@ protected:
bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemCheck(const LLSD& userdata);
bool onIMShowModesMenuItemEnable(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata);
static void onSlide(LLFloaterIMSessionTab *self); static void onSlide(LLFloaterIMSessionTab *self);
static void onCollapseToLine(LLFloaterIMSessionTab *self);
void reshapeFloater(bool collapse);
// refresh a visual state of the Call button // refresh a visual state of the Call button
void updateCallBtnState(bool callIsActive); void updateCallBtnState(bool callIsActive);
@ -135,17 +141,30 @@ protected:
void appendMessage(const LLChat& chat, const LLSD &args = 0); void appendMessage(const LLChat& chat, const LLSD &args = 0);
std::string appendTime(); std::string appendTime();
void assignResizeLimits();
S32 mFloaterExtraWidth;
bool mIsNearbyChat; bool mIsNearbyChat;
bool mIsP2PChat; bool mIsP2PChat;
bool mMessagePaneExpanded;
bool mIsParticipantListExpanded;
LLIMModel::LLIMSession* mSession; LLIMModel::LLIMSession* mSession;
// Participants list: model and view // Participants list: model and view
LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
LLUUID mSessionID; LLUUID mSessionID;
LLLayoutStack* mBodyStack;
LLLayoutStack* mParticipantListAndHistoryStack;
LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel
LLLayoutPanel* mRightPartPanel;
LLLayoutPanel* mContentPanel;
LLLayoutPanel* mToolbarPanel;
LLLayoutPanel* mInputButtonPanel;
LLParticipantList* getParticipantList(); LLParticipantList* getParticipantList();
conversations_widgets_map mConversationsWidgets; conversations_widgets_map mConversationsWidgets;
LLConversationViewModel mConversationViewModel; LLConversationViewModel mConversationViewModel;
@ -155,13 +174,17 @@ protected:
LLOutputMonitorCtrl* mSpeakingIndicator; LLOutputMonitorCtrl* mSpeakingIndicator;
LLChatHistory* mChatHistory; LLChatHistory* mChatHistory;
LLChatEntry* mInputEditor; LLChatEntry* mInputEditor;
int mInputEditorTopPad; // padding between input field and chat history LLLayoutPanel * mChatLayoutPanel;
int mInputEditorPad; // padding between input field and chat history
LLButton* mExpandCollapseLineBtn;
LLButton* mExpandCollapseBtn; LLButton* mExpandCollapseBtn;
LLButton* mTearOffBtn; LLButton* mTearOffBtn;
LLButton* mCloseBtn; LLButton* mCloseBtn;
LLButton* mGearBtn; LLButton* mGearBtn;
S32 mFloaterHeight;
private: private:
// Handling selection and contextual menu // Handling selection and contextual menu
@ -179,7 +202,7 @@ private:
* and avoid overlapping, since input chat field can be vertically expanded. * and avoid overlapping, since input chat field can be vertically expanded.
* Implementation: chat history bottom "follows" top+top_pad of input chat field * Implementation: chat history bottom "follows" top+top_pad of input chat field
*/ */
void reshapeChatHistory(); void reshapeChatLayoutPanel();
bool checkIfTornOff(); bool checkIfTornOff();
bool mIsHostAttached; bool mIsHostAttached;

View File

@ -443,6 +443,8 @@ BOOL LLFloaterPreference::postBuild()
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location); setCacheLocation(cache_location);
getChild<LLUICtrl>("log_path_string")->setEnabled(FALSE); // make it read-only but selectable
getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions")); getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions"));
@ -1572,7 +1574,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("send_im_to_email")->setEnabled(TRUE); getChildView("send_im_to_email")->setEnabled(TRUE);
getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email);
getChildView("favorites_on_login_check")->setEnabled(TRUE); getChildView("favorites_on_login_check")->setEnabled(TRUE);
getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case.
getChildView("log_path_button")->setEnabled(TRUE); getChildView("log_path_button")->setEnabled(TRUE);
getChildView("chat_font_size")->setEnabled(TRUE); getChildView("chat_font_size")->setEnabled(TRUE);
} }
@ -1667,7 +1668,10 @@ void LLFloaterPreference::onClickActionChange()
void LLFloaterPreference::onDeleteTranscripts() void LLFloaterPreference::onDeleteTranscripts()
{ {
LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); LLSD args;
args["FOLDER"] = gDirUtilp->getUserName();
LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", args, LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2));
} }
void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response)

View File

@ -154,149 +154,156 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
args["FROM"] = av_name.getCompleteName(); args["FROM"] = av_name.getCompleteName();
args["FROM_ID"] = msg["from_id"]; args["FROM_ID"] = msg["from_id"];
args["SESSION_ID"] = msg["session_id"]; args["SESSION_ID"] = msg["session_id"];
args["SESSION_TYPE"] = msg["session_type"];
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
} }
void on_new_message(const LLSD& msg) void on_new_message(const LLSD& msg)
{ {
std::string action; std::string user_preferences;
LLUUID participant_id = msg["from_id"].asUUID(); LLUUID participant_id = msg["from_id"].asUUID();
LLUUID session_id = msg["session_id"].asUUID(); LLUUID session_id = msg["session_id"].asUUID();
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
// determine action for this session
if (session_id.isNull())
{
action = gSavedSettings.getString("NotificationNearbyChatOptions");
}
else if(session->isP2PSessionType())
{
if (LLAvatarTracker::instance().isBuddy(participant_id))
{
action = gSavedSettings.getString("NotificationFriendIMOptions");
}
else
{
action = gSavedSettings.getString("NotificationNonFriendIMOptions");
}
}
else if(session->isAdHocSessionType())
{
action = gSavedSettings.getString("NotificationConferenceIMOptions");
}
else if(session->isGroupSessionType())
{
action = gSavedSettings.getString("NotificationGroupChatOptions");
}
// do not show notification which goes from agent // do not show notification which goes from agent
if (gAgent.getID() == participant_id) if (gAgent.getID() == participant_id)
{ {
return; return;
} }
// execution of the action // determine state of conversations floater
enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id) if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
{ {
return; conversations_floater_status = CLOSED;
}
else if ( !im_box->hasFocus() &&
(!session_floater || !LLFloater::isVisible(session_floater)
|| session_floater->isMinimized() || !session_floater->hasFocus()))
{
conversations_floater_status = NOT_ON_TOP;
}
else if (im_box->getSelectedSession() != session_id)
{
conversations_floater_status = ON_TOP;
}
else
{
conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;
} }
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); // determine user prefs for this session
if (session_id.isNull())
//session floater not focused (visible or not)
bool session_floater_not_focused = session_floater && !session_floater->hasFocus();
//conv. floater is closed
bool conversation_floater_is_closed =
!( im_box
&& im_box->isInVisibleChain()
&& !im_box->isMinimized());
//conversation floater not focused (visible or not)
bool conversation_floater_not_focused =
conversation_floater_is_closed || !im_box->hasFocus();
// sess. floater is open
bool session_floater_is_open =
session_floater
&& session_floater->isInVisibleChain()
&& !session_floater->isMinimized()
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized());
if ("toast" == action && !session_floater_is_open)
{ {
//User is not focused on conversation containing the message user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
if(session_floater_not_focused) }
else if(session->isP2PSessionType())
{
if (LLAvatarTracker::instance().isBuddy(participant_id))
{ {
if(!LLMuteList::getInstance()->isMuted(participant_id)) user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
{ }
im_box->flashConversationItemWidget(session_id, true); else
} {
//The conversation floater isn't focused/open user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
if(conversation_floater_not_focused) }
{ }
if(!LLMuteList::getInstance()->isMuted(participant_id) else if(session->isAdHocSessionType())
&& !gAgent.isDoNotDisturb()) {
{ user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
gToolBarView->flashCommand(LLCommandId("chat"), true); }
} else if(session->isGroupSessionType())
{
//Show IM toasts (upper right toasts) user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
// Skip toasting for system messages and for nearby chat
if(session_id.notNull() && participant_id.notNull())
{
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
}
}
}
} }
else if ("flash" == action) // actions:
// 0. nothing - exit
if (("none" == user_preferences ||
ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
&& session_floater->isMessagePaneExpanded())
{ {
if (!gAgent.isDoNotDisturb()) return;
{ }
im_box->flashConversationItemWidget(session_id, true);
if(conversation_floater_not_focused) // 1. open floater and [optional] surface it
if ("openconversations" == user_preferences &&
(CLOSED == conversations_floater_status
|| NOT_ON_TOP == conversations_floater_status))
{
if(!gAgent.isDoNotDisturb())
{
// Open conversations floater
LLFloaterReg::showInstance("im_container");
im_box->collapseMessagesPane(false);
if (session_floater)
{ {
//User is not focused on conversation containing the message if (session_floater->getHost())
gToolBarView->flashCommand(LLCommandId("chat"), true); {
if (NULL != im_box && im_box->isMinimized())
{
LLFloater::onClickMinimize(im_box);
}
}
else
{
if (session_floater->isMinimized())
{
LLFloater::onClickMinimize(session_floater);
}
}
} }
} }
else if(session_id.notNull() && participant_id.notNull()) else
{
//If a DND message, allow notification to be stored so upon DND exit
//useMostItrusiveIMNotification will be called to notify user a message exists
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
}
}
else if("openconversations" == action)
{
//User is not focused on conversation containing the message
if(session_floater_not_focused)
{ {
//Flash line item //If in DND mode, allow notification to be stored so upon DND exit
im_box->flashConversationItemWidget(session_id, true);
if(!gAgent.isDoNotDisturb())
{
//Surface conversations floater
LLFloaterReg::showInstance("im_container");
}
//If in DND mode, allow notification to be stored so upon DND exit
//useMostItrusiveIMNotification will be called to notify user a message exists //useMostItrusiveIMNotification will be called to notify user a message exists
if(session_id.notNull() if(session_id.notNull()
&& participant_id.notNull() && participant_id.notNull()
&& gAgent.isDoNotDisturb() && !session_floater->isShown())
&& !session_floater_is_open)
{ {
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
} }
} }
}
// 2. Flash line item
if ("openconversations" == user_preferences
|| ON_TOP == conversations_floater_status)
{
if(!LLMuteList::getInstance()->isMuted(participant_id))
{
im_box->flashConversationItemWidget(session_id, true);
}
}
// 3. Flash FUI button
if (("toast" == user_preferences || "flash" == user_preferences) &&
(CLOSED == conversations_floater_status
|| NOT_ON_TOP == conversations_floater_status))
{
if(!LLMuteList::getInstance()->isMuted(participant_id)
&& !gAgent.isDoNotDisturb())
{
gToolBarView->flashCommand(LLCommandId("chat"), true);
}
}
// 4. Toast
if ("toast" == user_preferences
|| !session_floater->isMessagePaneExpanded())
{
//Show IM toasts (upper right toasts)
// Skip toasting for system messages and for nearby chat
if(session_id.notNull() && participant_id.notNull())
{
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
}
} }
} }
@ -636,8 +643,7 @@ void LLIMModel::LLIMSession::loadHistory()
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{ {
return get_if_there(mId2SessionMap, session_id, return get_if_there(mId2SessionMap, session_id, (LLIMModel::LLIMSession*) NULL);
(LLIMModel::LLIMSession*) NULL);
} }
//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code //*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code
@ -990,6 +996,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co
arg["from"] = from; arg["from"] = from;
arg["from_id"] = from_id; arg["from_id"] = from_id;
arg["time"] = LLLogChat::timestamp(false); arg["time"] = LLLogChat::timestamp(false);
arg["session_type"] = session->mSessionType;
mNewMsgSignal(arg); mNewMsgSignal(arg);
return true; return true;
@ -2633,7 +2640,7 @@ void LLIMMgr::addMessage(
if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
{ {
// Evaluate if we need to skip this message when that setting is true (default is false) // Evaluate if we need to skip this message when that setting is true (default is false)
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends... skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
skip_message &= !session->isGroupSessionType(); // Do not skip group chats... skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself
@ -2649,7 +2656,7 @@ void LLIMMgr::addMessage(
{ {
LLFloaterReg::showInstance("im_container"); LLFloaterReg::showInstance("im_container");
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->
flashConversationItemWidget(session_id, true); flashConversationItemWidget(new_session_id, true);
} }
} }
@ -2804,7 +2811,7 @@ LLUUID LLIMMgr::addSession(
} }
} }
bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); bool new_session = (LLIMModel::getInstance()->findIMSession(session_id) == NULL);
//works only for outgoing ad-hoc sessions //works only for outgoing ad-hoc sessions
if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size()) if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())

View File

@ -444,7 +444,7 @@ std::string LLLogChat::oldLogFileName(std::string filename)
} }
// static // static
void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions) void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions)
{ {
// get Users log directory // get Users log directory
std::string dirname = gDirUtilp->getPerAccountChatLogsDir(); std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
@ -452,9 +452,6 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
// add final OS dependent delimiter // add final OS dependent delimiter
dirname += gDirUtilp->getDirDelimiter(); dirname += gDirUtilp->getDirDelimiter();
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
LLDirIterator iter(dirname, pattern); LLDirIterator iter(dirname, pattern);
std::string filename; std::string filename;
while (iter.next(filename)) while (iter.next(filename))
@ -490,6 +487,22 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
} }
} }
// static
void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions)
{
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
findTranscriptFiles(pattern, list_of_transcriptions);
}
// static
void LLLogChat::getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions)
{
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + ".backup*";
findTranscriptFiles(pattern, list_of_transcriptions);
}
//static //static
boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb) boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb)
{ {
@ -581,6 +594,7 @@ void LLLogChat::deleteTranscripts()
{ {
std::vector<std::string> list_of_transcriptions; std::vector<std::string> list_of_transcriptions;
getListOfTranscriptFiles(list_of_transcriptions); getListOfTranscriptFiles(list_of_transcriptions);
getListOfTranscriptBackupFiles(list_of_transcriptions);
BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions) BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions)
{ {

View File

@ -49,7 +49,9 @@ public:
const std::string& from, const std::string& from,
const LLUUID& from_id, const LLUUID& from_id,
const std::string& line); const std::string& line);
static void findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions);
static void getListOfTranscriptFiles(std::vector<std::string>& list); static void getListOfTranscriptFiles(std::vector<std::string>& list);
static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());

View File

@ -105,6 +105,8 @@ bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) co
bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
{ {
LL_INFOS("LLNotificationStorage") << "starting read '" << mFileName << "'" << LL_ENDL;
bool didFileRead; bool didFileRead;
pNotificationData.clear(); pNotificationData.clear();
@ -126,6 +128,8 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
} }
} }
LL_INFOS("LLNotificationStorage") << "ending read '" << mFileName << "'" << LL_ENDL;
return didFileRead; return didFileRead;
} }

View File

@ -611,10 +611,10 @@ BOOL LLPanelPeople::postBuild()
mGroupList->setNoItemsMsg(getString("no_groups_msg")); mGroupList->setNoItemsMsg(getString("no_groups_msg"));
mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg")); mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg"));
mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyPeopleContextMenu);
mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false); setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
@ -1143,7 +1143,10 @@ void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn)
uuid_vec_t selected_uuids; uuid_vec_t selected_uuids;
getCurrentItemIDs(selected_uuids); getCurrentItemIDs(selected_uuids);
// Spawn at bottom left corner of the button. // Spawn at bottom left corner of the button.
LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); if (getActiveTabName() == NEARBY_TAB_NAME)
LLPanelPeopleMenus::gNearbyPeopleContextMenu.show(btn, selected_uuids, 0, 0);
else
LLPanelPeopleMenus::gPeopleContextMenu.show(btn, selected_uuids, 0, 0);
} }
void LLPanelPeople::onImButtonClicked() void LLPanelPeople::onImButtonClicked()

View File

@ -39,15 +39,18 @@
#include "llcallingcard.h" // for LLAvatarTracker #include "llcallingcard.h" // for LLAvatarTracker
#include "lllogchat.h" #include "lllogchat.h"
#include "llviewermenu.h" // for gMenuHolder #include "llviewermenu.h" // for gMenuHolder
#include "llconversationmodel.h"
#include "llviewerobjectlist.h"
namespace LLPanelPeopleMenus namespace LLPanelPeopleMenus
{ {
NearbyMenu gNearbyMenu; PeopleContextMenu gPeopleContextMenu;
NearbyPeopleContextMenu gNearbyPeopleContextMenu;
//== NearbyMenu =============================================================== //== PeopleContextMenu ===============================================================
LLContextMenu* NearbyMenu::createMenu() LLContextMenu* PeopleContextMenu::createMenu()
{ {
// set up the callbacks for all of the avatar menu items // set up the callbacks for all of the avatar menu items
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@ -64,7 +67,8 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendDialog, id)); registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendDialog, id));
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id)); registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id)); registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id));
registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
registrar.add("Avatar.ZoomIn", boost::bind(&handle_zoom_to_object, id));
registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id)); registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id));
registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id)); registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id));
registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id));
@ -72,33 +76,72 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id));
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id)); registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));
// create the context menu from the XUI // create the context menu from the XUI
menu = createFromFile("menu_people_nearby.xml"); menu = createFromFile("menu_people_nearby.xml");
buildContextMenu(*menu, 0x0);
} }
else else
{ {
// Set up for multi-selected People // Set up for multi-selected People
// registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null)); registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null));
registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs));
// registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented // registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented
// registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
// create the context menu from the XUI // create the context menu from the XUI
menu = createFromFile("menu_people_nearby_multiselect.xml"); menu = createFromFile("menu_people_nearby_multiselect.xml");
buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION);
} }
return menu; return menu;
} }
bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if (flags & ITEM_IN_MULTI_SELECTION)
{
items.push_back(std::string("add_friends"));
items.push_back(std::string("remove_friends"));
items.push_back(std::string("im"));
items.push_back(std::string("call"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("offer_teleport"));
}
else
{
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("block_unblock"));
}
hide_context_entries(menu, items, disabled_items);
}
bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata)
{ {
if(gAgent.getID() == mUUIDs.front()) if(gAgent.getID() == mUUIDs.front())
{ {
@ -170,6 +213,12 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
{ {
return LLAvatarActions::canCall(); return LLAvatarActions::canCall();
} }
else if (item == std::string("can_zoom_in"))
{
const LLUUID& id = mUUIDs.front();
return gObjectList.findObject(id);
}
else if (item == std::string("can_show_on_map")) else if (item == std::string("can_show_on_map"))
{ {
const LLUUID& id = mUUIDs.front(); const LLUUID& id = mUUIDs.front();
@ -193,7 +242,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
return false; return false;
} }
bool NearbyMenu::checkContextMenuItem(const LLSD& userdata) bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
{ {
std::string item = userdata.asString(); std::string item = userdata.asString();
const LLUUID& id = mUUIDs.front(); const LLUUID& id = mUUIDs.front();
@ -206,11 +255,50 @@ bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
return false; return false;
} }
void NearbyMenu::offerTeleport() void PeopleContextMenu::offerTeleport()
{ {
// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(), // boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
// so we have to use a wrapper. // so we have to use a wrapper.
LLAvatarActions::offerTeleport(mUUIDs); LLAvatarActions::offerTeleport(mUUIDs);
} }
//== NearbyPeopleContextMenu ===============================================================
void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if (flags & ITEM_IN_MULTI_SELECTION)
{
items.push_back(std::string("add_friends"));
items.push_back(std::string("remove_friends"));
items.push_back(std::string("im"));
items.push_back(std::string("call"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("offer_teleport"));
}
else
{
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
items.push_back(std::string("zoom_in"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("block_unblock"));
}
hide_context_entries(menu, items, disabled_items);
}
} // namespace LLPanelPeopleMenus } // namespace LLPanelPeopleMenus

View File

@ -33,19 +33,33 @@ namespace LLPanelPeopleMenus
{ {
/** /**
* Menu used in the nearby people list. * Menu used in the people lists.
*/ */
class NearbyMenu : public LLListContextMenu class PeopleContextMenu : public LLListContextMenu
{ {
public: public:
/*virtual*/ LLContextMenu* createMenu(); /*virtual*/ LLContextMenu* createMenu();
protected:
virtual void buildContextMenu(class LLMenuGL& menu, U32 flags);
private: private:
bool enableContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata);
void offerTeleport(); void offerTeleport();
}; };
extern NearbyMenu gNearbyMenu; /**
* Menu used in the nearby people list.
*/
class NearbyPeopleContextMenu : public PeopleContextMenu
{
protected:
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
};
extern PeopleContextMenu gPeopleContextMenu;
extern NearbyPeopleContextMenu gNearbyPeopleContextMenu;
} // namespace LLPanelPeopleMenus } // namespace LLPanelPeopleMenus

View File

@ -87,6 +87,8 @@ void LLPersistentNotificationStorage::loadNotifications()
{ {
LLFastTimer _(FTM_LOAD_NOTIFICATIONS); LLFastTimer _(FTM_LOAD_NOTIFICATIONS);
LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL;
LLNotifications::instance().getChannel("Persistent")-> LLNotifications::instance().getChannel("Persistent")->
connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
@ -129,6 +131,8 @@ void LLPersistentNotificationStorage::loadNotifications()
notification_channel->hideToast(notification->getID()); notification_channel->hideToast(notification->getID());
} }
} }
LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;
} }
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)

View File

@ -38,6 +38,8 @@
#include "llvoavatar.h" #include "llvoavatar.h"
#include "llworld.h" #include "llworld.h"
extern LLControlGroup gSavedSettings;
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
@ -311,6 +313,7 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mModerateModeHandledFirstTime(false), mModerateModeHandledFirstTime(false),
mSpeakerListUpdated(false) mSpeakerListUpdated(false)
{ {
mGetListTime.reset();
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay); mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
@ -409,12 +412,10 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// update status of all current speakers // update status of all current speakers
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()); BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();) for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++)
{ {
LLUUID speaker_id = speaker_it->first; LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second; LLSpeaker* speakerp = speaker_it->second;
speaker_map_t::iterator cur_speaker_it = speaker_it++;
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id)) if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
{ {
@ -539,30 +540,39 @@ void LLSpeakerMgr::updateSpeakerList()
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
if (session->isGroupSessionType() && (mSpeakers.size() <= 1)) if (session->isGroupSessionType() && (mSpeakers.size() <= 1))
{ {
const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout");
// For groups, we need to hit the group manager. // For groups, we need to hit the group manager.
// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id);
if (!gdatap) if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout))
{ {
// Request the data the first time around // Request the data the first time around
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id);
} }
else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
{ {
// Add group members when we get the complete list (note: can take a while before we get that list) // Add group members when we get the complete list (note: can take a while before we get that list)
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers");
S32 updated = 0;
while (member_it != gdatap->mMembers.end()) while (member_it != gdatap->mMembers.end())
{ {
LLGroupMemberData* member = member_it->second; LLGroupMemberData* member = member_it->second;
// Add only the members who are online LLUUID id = member_it->first;
if (member->getOnlineStatus() == "Online") // Add only members who are online and not already in the list
if ((member->getOnlineStatus() == "Online") && (mSpeakers.find(id) == mSpeakers.end()))
{ {
LLPointer<LLSpeaker> speakerp = setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
updated++;
} }
++member_it; ++member_it;
// Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop
// *TODO : solve the perf issue of having several hundreds of widgets in the conversation list
if (updated >= load_group_max_members)
break;
} }
mSpeakerListUpdated = true; mSpeakerListUpdated = true;
} }
} }
else if (mSpeakers.size() == 0) else if (mSpeakers.size() == 0)

View File

@ -264,6 +264,7 @@ protected:
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t; typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
speaker_map_t mSpeakers; speaker_map_t mSpeakers;
bool mSpeakerListUpdated; bool mSpeakerListUpdated;
LLTimer mGetListTime;
speaker_list_t mSpeakersSorted; speaker_list_t mSpeakersSorted;
LLFrameTimer mSpeechTimer; LLFrameTimer mSpeechTimer;

View File

@ -1038,7 +1038,6 @@ void render_hud_attachments()
if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
{ {
LLCamera hud_cam = *LLViewerCamera::getInstance(); LLCamera hud_cam = *LLViewerCamera::getInstance();
LLVector3 origin = hud_cam.getOrigin();
hud_cam.setOrigin(-1.f,0,0); hud_cam.setOrigin(-1.f,0,0);
hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);

View File

@ -2382,7 +2382,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false); LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false);
break; break;
case IM_NOTHING_SPECIAL: case IM_NOTHING_SPECIAL: // p2p IM
// Don't show dialog, just do IM // Don't show dialog, just do IM
if (!gAgent.isGodlike() if (!gAgent.isGodlike()
&& gAgent.getRegion()->isPrelude() && gAgent.getRegion()->isPrelude()
@ -2783,47 +2783,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
} }
break; break;
case IM_SESSION_SEND:
{
if (is_do_not_disturb)
{
return;
}
// Only show messages if we have a session open (which
// should happen after you get an "invitation"
if ( !gIMMgr->hasSession(session_id) )
{
return;
}
// standard message, not from system
std::string saved;
if(offline == IM_OFFLINE)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
buffer = saved + message;
BOOL is_this_agent = FALSE;
if(from_id == gAgentID)
{
is_this_agent = TRUE;
}
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
break;
case IM_FROM_TASK: case IM_FROM_TASK:
{ {
if (is_do_not_disturb && !is_owned_by_me) if (is_do_not_disturb && !is_owned_by_me)
@ -2922,6 +2881,76 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group); LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group);
} }
break; break;
case IM_SESSION_SEND: // ad-hoc or group IMs
// Only show messages if we have a session open (which
// should happen after you get an "invitation"
if ( !gIMMgr->hasSession(session_id) )
{
return;
}
else if (offline == IM_ONLINE && is_do_not_disturb)
{
// return a standard "do not disturb" message, but only do it to online IM
// (i.e. not other auto responses and not store-and-forward IM)
if (!gIMMgr->hasSession(session_id))
{
// if there is not a panel for this conversation (i.e. it is a new IM conversation
// initiated by the other party) then...
send_do_not_disturb_message(msg, from_id, session_id);
}
// now store incoming IM in chat history
buffer = message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
// add to IM panel, but do not bother the user
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
else
{
// standard message, not from system
std::string saved;
if(offline == IM_OFFLINE)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
buffer = saved + message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
break;
case IM_FROM_TASK_AS_ALERT: case IM_FROM_TASK_AS_ALERT:
if (is_do_not_disturb && !is_owned_by_me) if (is_do_not_disturb && !is_owned_by_me)
{ {

View File

@ -2827,7 +2827,6 @@ void LLViewerWindow::updateUI()
BOOL handled = FALSE; BOOL handled = FALSE;
BOOL handled_by_top_ctrl = FALSE;
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
LLView* captor_view = dynamic_cast<LLView*>(mouse_captor); LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
@ -3012,7 +3011,6 @@ void LLViewerWindow::updateUI()
S32 local_x, local_y; S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask); handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
handled_by_top_ctrl = TRUE;
} }
if ( !handled ) if ( !handled )

View File

@ -675,7 +675,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mBelowWater(FALSE), mBelowWater(FALSE),
mLastAppearanceBlendTime(0.f), mLastAppearanceBlendTime(0.f),
mAppearanceAnimating(FALSE), mAppearanceAnimating(FALSE),
mNameString(), mNameIsSet(false),
mTitle(), mTitle(),
mNameAway(false), mNameAway(false),
mNameDoNotDisturb(false), mNameDoNotDisturb(false),
@ -2994,43 +2994,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return; return;
} }
BOOL new_name = FALSE; BOOL new_name = FALSE;
if (visible_chat != mVisibleChat) if (visible_chat != mVisibleChat)
{ {
mVisibleChat = visible_chat; mVisibleChat = visible_chat;
new_name = TRUE; new_name = TRUE;
} }
if (sRenderGroupTitles != mRenderGroupTitles)
{
mRenderGroupTitles = sRenderGroupTitles;
new_name = TRUE;
}
// First Calculate Alpha if (sRenderGroupTitles != mRenderGroupTitles)
// If alpha > 0, create mNameText if necessary, otherwise delete it {
F32 alpha = 0.f; mRenderGroupTitles = sRenderGroupTitles;
if (mAppAngle > 5.f) new_name = TRUE;
{ }
const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) // First Calculate Alpha
{ // If alpha > 0, create mNameText if necessary, otherwise delete it
alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; F32 alpha = 0.f;
} if (mAppAngle > 5.f)
else {
{ const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
// ...not fading, full alpha if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
alpha = 1.f; {
} alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
} }
else if (mAppAngle > 2.f) else
{ {
// far away is faded out also // ...not fading, full alpha
alpha = (mAppAngle-2.f)/3.f; alpha = 1.f;
} }
}
else if (mAppAngle > 2.f)
{
// far away is faded out also
alpha = (mAppAngle-2.f)/3.f;
}
if (alpha <= 0.f) if (alpha <= 0.f)
{ {
if (mNameText) if (mNameText)
{ {
mNameText->markDead(); mNameText->markDead();
@ -3040,19 +3040,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return; return;
} }
if (!mNameText) if (!mNameText)
{ {
mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
LLHUDObject::LL_HUD_NAME_TAG) ); LLHUDObject::LL_HUD_NAME_TAG) );
//mNameText->setMass(10.f); //mNameText->setMass(10.f);
mNameText->setSourceObject(this); mNameText->setSourceObject(this);
mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
mNameText->setVisibleOffScreen(TRUE); mNameText->setVisibleOffScreen(TRUE);
mNameText->setMaxLines(11); mNameText->setMaxLines(11);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
sNumVisibleChatBubbles++; sNumVisibleChatBubbles++;
new_name = TRUE; new_name = TRUE;
} }
idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagPosition(root_pos_last);
idleUpdateNameTagText(new_name); idleUpdateNameTagText(new_name);
@ -3096,7 +3096,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
} }
// Rebuild name tag if state change detected // Rebuild name tag if state change detected
if (mNameString.empty() if (!mNameIsSet
|| new_name || new_name
|| (!title && !mTitle.empty()) || (!title && !mTitle.empty())
|| (title && mTitle != title->getString()) || (title && mTitle != title->getString())
@ -3291,18 +3291,18 @@ void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color,
{ {
mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font); mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
} }
mNameString += line; mNameIsSet |= !line.empty();
mNameString += '\n';
} }
void LLVOAvatar::clearNameTag() void LLVOAvatar::clearNameTag()
{ {
mNameString.clear(); mNameIsSet = false;
if (mNameText) if (mNameText)
{ {
mNameText->setLabel(""); mNameText->setLabel("");
mNameText->setString( "" ); mNameText->setString("");
} }
mTimeVisible.reset();
} }
//static //static

View File

@ -939,7 +939,7 @@ protected:
static void getAnimLabels(LLDynamicArray<std::string>* labels); static void getAnimLabels(LLDynamicArray<std::string>* labels);
static void getAnimNames(LLDynamicArray<std::string>* names); static void getAnimNames(LLDynamicArray<std::string>* names);
private: private:
std::string mNameString; // UTF-8 title + name + status bool mNameIsSet;
std::string mTitle; std::string mTitle;
bool mNameAway; bool mNameAway;
bool mNameDoNotDisturb; bool mNameDoNotDisturb;

View File

@ -1258,7 +1258,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateCreatingSessionGroup //MARK: stateCreatingSessionGroup
case stateCreatingSessionGroup: case stateCreatingSessionGroup:
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{ {
// *TODO: Question: is this the right way out of this state // *TODO: Question: is this the right way out of this state
setState(stateSessionTerminated); setState(stateSessionTerminated);
@ -1274,7 +1274,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRetrievingParcelVoiceInfo //MARK: stateRetrievingParcelVoiceInfo
case stateRetrievingParcelVoiceInfo: case stateRetrievingParcelVoiceInfo:
// wait until parcel voice info is received. // wait until parcel voice info is received.
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{ {
// if a terminate request has been received, // if a terminate request has been received,
// bail and go to the stateSessionTerminated // bail and go to the stateSessionTerminated
@ -1294,7 +1294,7 @@ void LLVivoxVoiceClient::stateMachine()
// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync. // Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
sendFriendsListUpdates(); sendFriendsListUpdates();
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized) if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{ {
// TODO: Question: Is this the right way out of this state? // TODO: Question: Is this the right way out of this state?
setState(stateSessionTerminated); setState(stateSessionTerminated);
@ -1442,7 +1442,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRunning //MARK: stateRunning
case stateRunning: // steady state case stateRunning: // steady state
// Disabling voice or disconnect requested. // Disabling voice or disconnect requested.
if(!mVoiceEnabled && mIsInitialized || mSessionTerminateRequested) if((!mVoiceEnabled && mIsInitialized) || mSessionTerminateRequested)
{ {
leaveAudioSession(); leaveAudioSession();
} }
@ -2671,33 +2671,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
{ {
buddyListEntry *buddy = findBuddy(id); buddyListEntry *buddy = findBuddy(id);
// Make sure we don't add a name before it's been looked up. // Make sure we don't add a name before it's been looked up in the avatar name cache
LLAvatarName av_name; LLAvatarName av_name;
if(LLAvatarNameCache::get(id, &av_name)) if (LLAvatarNameCache::get(id, &av_name))
{ {
// *NOTE: For now, we feed legacy names to Vivox because I don't know // *NOTE: We feed legacy names to Vivox because we don't know if their service
// if their service can support a mix of new and old clients with // can support a mix of new and old clients with different sorts of names.
// different sorts of names.
std::string name = av_name.getAccountName(); std::string name = av_name.getAccountName();
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
bool canSeeMeOnline = false;
if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
canSeeMeOnline = true;
// When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary. if (buddy)
if(buddy)
{ {
// This buddy is already in both lists. // This buddy is already in both lists (vivox buddies and avatar cache).
// Trust the avatar cache more for the display name (vivox display name are notoriously wrong)
if(name != buddy->mDisplayName) buddy->mDisplayName = name;
{
// The buddy is in the list with the wrong name. Update it with the correct name.
LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
buddy->mDisplayName = name;
buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
}
} }
else else
{ {
@ -2706,20 +2692,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
buddy->mUUID = id; buddy->mUUID = id;
} }
// In all the above cases, the buddy is in the SL friends list (which is how we got here). const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
buddy->mInSLFriends = true; buddy->mCanSeeMeOnline = (relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
buddy->mCanSeeMeOnline = canSeeMeOnline; // In all the above cases, the buddy is in the SL friends list and tha name has been resolved (which is how we got here).
buddy->mNameResolved = true; buddy->mNameResolved = true;
buddy->mInSLFriends = true;
} }
else else
{ {
// This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has. // This name hasn't been looked up yet in the avatar cache. Don't do anything with this buddy list entry until it has.
if(buddy) if (buddy)
{ {
buddy->mNameResolved = false; buddy->mNameResolved = false;
} }
// Initiate a lookup. // Initiate a lookup.
// The "lookup completed" callback will ensure that the friends list is rechecked after it completes. // The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
lookupName(id); lookupName(id);
@ -2827,13 +2812,12 @@ void LLVivoxVoiceClient::sendFriendsListUpdates()
{ {
std::ostringstream stream; std::ostringstream stream;
if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate)) if(buddy->mInSLFriends && !buddy->mInVivoxBuddies)
{ {
if(mNumberOfAliases > 0) if(mNumberOfAliases > 0)
{ {
// Add (or update) this entry in the vivox buddy list // Add (or update) this entry in the vivox buddy list
buddy->mInVivoxBuddies = true; buddy->mInVivoxBuddies = true;
buddy->mNeedsNameUpdate = false;
LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL; LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
stream stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">" << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
@ -5859,7 +5843,6 @@ LLVivoxVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
mNameResolved = false; mNameResolved = false;
mInVivoxBuddies = false; mInVivoxBuddies = false;
mInSLFriends = false; mInSLFriends = false;
mNeedsNameUpdate = false;
} }
void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName) void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
@ -5884,25 +5867,21 @@ LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::stri
buddyListEntry *result = NULL; buddyListEntry *result = NULL;
buddyListMap::iterator iter = mBuddyListMap.find(uri); buddyListMap::iterator iter = mBuddyListMap.find(uri);
if(iter != mBuddyListMap.end()) if (iter != mBuddyListMap.end())
{ {
// Found a matching buddy already in the map. // Found a matching buddy already in the map.
LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL; LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
result = iter->second; result = iter->second;
} }
if(!result) if (!result)
{ {
// participant isn't already in one list or the other. // participant isn't already in one list or the other.
LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL; LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
result = new buddyListEntry(uri); result = new buddyListEntry(uri);
result->mDisplayName = displayName; result->mDisplayName = displayName;
if(IDFromName(uri, result->mUUID)) if (!IDFromName(uri, result->mUUID))
{
// Extracted UUID from name successfully.
}
else
{ {
LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL; LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
} }
@ -7272,7 +7251,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
void LLVivoxProtocolParser::EndTag(const char *tag) void LLVivoxProtocolParser::EndTag(const char *tag)
{ {
const std::string& string = textBuffer; const std::string& string = textBuffer;
responseDepth--; responseDepth--;
if (ignoringTags) if (ignoringTags)
@ -7371,6 +7350,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
} }
else if (!stricmp("Buddy", tag)) else if (!stricmp("Buddy", tag))
{ {
// NOTE : Vivox does *not* give reliable display name for Buddy tags
// We don't take those very seriously as a result...
LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString); LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString);
} }
else if (!stricmp("BlockRule", tag)) else if (!stricmp("BlockRule", tag))

View File

@ -584,7 +584,6 @@ protected:
bool mNameResolved; bool mNameResolved;
bool mInSLFriends; bool mInSLFriends;
bool mInVivoxBuddies; bool mInVivoxBuddies;
bool mNeedsNameUpdate;
}; };
typedef std::map<std::string, buddyListEntry*> buddyListMap; typedef std::map<std::string, buddyListEntry*> buddyListMap;

View File

@ -965,8 +965,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
S32 text_x = x; S32 text_x = x;
S32 text_y = (S32)(y - sTrackCircleImage->getHeight()/2 - font->getLineHeight()); S32 text_y = (S32)(y - sTrackCircleImage->getHeight()/2 - font->getLineHeight());
BOOL is_in_window = true;
if( x < 0 if( x < 0
|| y < 0 || y < 0
|| x >= getRect().getWidth() || x >= getRect().getWidth()
@ -979,7 +977,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
text_x = sTrackingArrowX; text_x = sTrackingArrowX;
text_y = sTrackingArrowY; text_y = sTrackingArrowY;
} }
is_in_window = false;
} }
else if (LLTracker::getTrackingStatus() == LLTracker::TRACKING_LOCATION && else if (LLTracker::getTrackingStatus() == LLTracker::TRACKING_LOCATION &&
LLTracker::getTrackedLocationType() != LLTracker::LOCATION_NOTHING) LLTracker::getTrackedLocationType() != LLTracker::LOCATION_NOTHING)

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -171,6 +171,8 @@ with the same filename but different name
<texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" /> <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" />
<texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" /> <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" />
<texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" /> <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" />
<texture name="Conv_collapse_to_one_line" file_name="icons/collapse_to_one_line.png" preload="false" />
<texture name="Conv_expand_one_line" file_name="icons/expand_one_liner.png" preload="false" />
<texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" /> <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" />
<texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" /> <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" />
<texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" />

View File

@ -61,7 +61,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
menu_filename="menu_participant_view.xml" menu_filename="menu_participant_view.xml"
layout="topleft" layout="topleft"
left="10" left="5"
name="sort_btn" name="sort_btn"
tool_tip="View/sort options" tool_tip="View/sort options"
top="5" top="5"
@ -75,7 +75,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="4" left_pad="2"
name="add_btn" name="add_btn"
tool_tip="Start a new conversation" tool_tip="Start a new conversation"
width="31"/> width="31"/>
@ -88,7 +88,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="4" left_pad="2"
name="speak_btn" name="speak_btn"
tool_tip="Speak with people using your microphone" tool_tip="Speak with people using your microphone"
width="31"/> width="31"/>
@ -114,7 +114,7 @@
</layout_panel> </layout_panel>
</layout_stack> </layout_stack>
<panel <panel
bottom="-5" bottom="-1"
follows="all" follows="all"
layout="topleft" layout="topleft"
name="conversations_list_panel" name="conversations_list_panel"
@ -129,7 +129,7 @@
name="messages_layout_panel" name="messages_layout_panel"
expanded_min_dim="222"> expanded_min_dim="222">
<panel_container <panel_container
bottom="-5" bottom="-1"
follows="all" follows="all"
layout="topleft" layout="topleft"
left="0" left="0"

View File

@ -14,11 +14,16 @@
width="394" width="394"
can_resize="true" can_resize="true"
can_tear_off="false" can_tear_off="false"
min_width="340"
min_height="190" min_height="190"
positioning="relative"> positioning="relative">
<floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string>
<floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string>
<floater.string
name="collapseline_icon"
value="Conv_collapse_to_one_line"/>
<floater.string
name="expandline_icon"
value="Conv_expand_one_line"/>
<floater.string <floater.string
name="collapse_icon" name="collapse_icon"
value="Conv_toolbar_collapse"/> value="Conv_toolbar_collapse"/>
@ -65,14 +70,28 @@
top="0" top="0"
left="0" left="0"
height="355" height="355"
width="394"> width="394">
<panel <layout_stack
animate="false"
default_tab_group="2"
follows="all"
height="355"
width="394"
layout="topleft"
orientation="vertical"
name="main_stack"
tab_group="1"
top="0"
left="0">
<layout_panel
follows="left|top|right" follows="left|top|right"
layout="topleft" layout="topleft"
name="toolbar_panel" name="toolbar_panel"
top="0" top="0"
left="0" left="0"
height="35" height="35"
min_height="35"
width="394"> width="394">
<menu_button <menu_button
menu_filename="menu_im_session_showmodes.xml" menu_filename="menu_im_session_showmodes.xml"
@ -98,7 +117,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="4" left_pad="2"
name="gear_btn" name="gear_btn"
visible="false" visible="false"
tool_tip="Actions on selected person" tool_tip="Actions on selected person"
@ -113,7 +132,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="4" left_pad="2"
name="add_btn" name="add_btn"
tool_tip="Add someone to this conversation" tool_tip="Add someone to this conversation"
width="31"/> width="31"/>
@ -126,7 +145,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="4" left_pad="2"
name="voice_call_btn" name="voice_call_btn"
tool_tip="Open voice connection" tool_tip="Open voice connection"
width="31"/> width="31"/>
@ -151,7 +170,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left="283" left="292"
name="close_btn" name="close_btn"
tool_tip="End this conversation" tool_tip="End this conversation"
width="31" /> width="31" />
@ -164,7 +183,7 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="5" left_pad="2"
name="expand_collapse_btn" name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane" tool_tip="Collapse/Expand this pane"
width="31" /> width="31" />
@ -177,15 +196,22 @@
image_unselected="Toolbar_Middle_Off" image_unselected="Toolbar_Middle_Off"
layout="topleft" layout="topleft"
top="5" top="5"
left_pad="5" left_pad="2"
name="tear_off_btn" name="tear_off_btn"
width="31" /> width="31" />
</panel> </layout_panel>
<layout_panel
name="body_panel"
follows="all"
width="394"
height="235"
user_resize="false"
auto_resize="true">
<layout_stack <layout_stack
animate="true" animate="true"
default_tab_group="2" default_tab_group="2"
follows="all" follows="all"
height="310" height="275"
width="394" width="394"
layout="topleft" layout="topleft"
orientation="horizontal" orientation="horizontal"
@ -196,11 +222,12 @@
<layout_panel <layout_panel
name="speakers_list_panel" name="speakers_list_panel"
follows="all" follows="all"
min_width="115" expanded_min_dim="115"
min_dim="0"
width="150" width="150"
height="310" height="275"
user_resize="true" user_resize="true"
auto_resize="true"> auto_resize="false">
</layout_panel> </layout_panel>
<layout_panel <layout_panel
default_tab_group="3" default_tab_group="3"
@ -208,26 +235,26 @@
tab_group="2" tab_group="2"
follows="all" follows="all"
top="0" top="0"
height="310" height="275"
width="244" width="244"
layout="topleft" layout="topleft"
user_resize="true" user_resize="true"
auto_resize="true" auto_resize="true"
visible="true" visible="true"
name="left_part_holder" name="right_part_holder"
min_width="221"> min_width="221">
<panel <panel
name="trnsAndChat_panel" name="trnsAndChat_panel"
follows="all" follows="all"
layout="topleft" layout="topleft"
visible="true" visible="true"
height="275" height="240"
width="244"> width="244">
<layout_stack <layout_stack
animate="true" animate="true"
default_tab_group="2" default_tab_group="2"
follows="all" follows="all"
height="275" height="240"
width="244" width="244"
layout="topleft" layout="topleft"
visible="true" visible="true"
@ -239,6 +266,7 @@
left="0"> left="0">
<layout_panel <layout_panel
auto_resize="false" auto_resize="false"
user_resize="false"
height="26" height="26"
layout="topleft" layout="topleft"
left_delta="0" left_delta="0"
@ -258,7 +286,6 @@
width="230" /> width="230" />
</layout_panel> </layout_panel>
<layout_panel <layout_panel
height="248"
width="210" width="210"
layout="topleft" layout="topleft"
follows="all" follows="all"
@ -266,43 +293,109 @@
top_delta="0" top_delta="0"
bottom="0" bottom="0"
visible="true" visible="true"
user_resize="true" user_resize="false"
auto_resize="true" auto_resize="true"
name="chat_holder"> name="chat_holder">
<chat_history <chat_history
font="SansSerifSmall" font="SansSerifSmall"
follows="all" follows="all"
visible="true" visible="true"
height="240"
name="chat_history" name="chat_history"
parse_highlights="true" parse_highlights="true"
parse_urls="true" parse_urls="true"
layout="topleft"
right="-5" right="-5"
left="5"> left="5"
top="0"
bottom="1">
</chat_history> </chat_history>
</layout_panel> </layout_panel>
</layout_stack> </layout_stack>
</panel> </panel>
<chat_editor </layout_panel>
</layout_stack>
</layout_panel>
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
right="0"
top_delta="0"
bottom="0" bottom="0"
visible="true"
user_resize="false"
auto_resize="false"
name="chat_layout_panel">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
height="35"
right="0"
layout="topleft"
orientation="horizontal"
name="input_panels"
top_pad="0"
left="0">
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
top_delta="0"
bottom="0"
visible="true"
user_resize="false"
auto_resize="true"
name="input_editor_layout_panel">
<chat_editor
expand_lines_count="5" expand_lines_count="5"
follows="left|right|bottom" follows="left|right|bottom"
font="SansSerifSmall" font="SansSerifSmall"
visible="true" visible="true"
height="20" height="20"
is_expandable="true" is_expandable="true"
label="To" label="To"
text_tentative_color="TextFgTentativeColor" text_tentative_color="TextFgTentativeColor"
layout="bottomleft" layout="topleft"
name="chat_editor" name="chat_editor"
max_length="1023" max_length="1023"
spellcheck="true" spellcheck="true"
tab_group="3" tab_group="3"
width="220" width="160"
left="10" top="6"
left="5"
right="-5"
wrap="true"> wrap="true">
</chat_editor> </chat_editor>
</layout_panel> </layout_panel>
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
top_delta="0"
bottom="0"
width="35"
visible="true"
user_resize="false"
auto_resize="false"
name="input_button_layout_panel">
<button
follows="left|right|bottom"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_expand_one_line"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
name="minz_btn"
tool_tip="Shows/hides message panel"
width="28"/>
</layout_panel>
</layout_stack>
</layout_panel>
</layout_stack> </layout_stack>
</view> </view>
</floater> </floater>

View File

@ -89,7 +89,14 @@
<on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> <on_click function="Avatar.DoToSelected" parameter="invite_to_group" />
<on_enable function="Avatar.EnableItem" parameter="can_invite" /> <on_enable function="Avatar.EnableItem" parameter="can_invite" />
</menu_item_call> </menu_item_call>
<menu_item_separator layout="topleft" name="separator_invite_to_group"/> <menu_item_separator layout="topleft" name="separator_invite_to_group"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<on_click function="Avatar.DoToSelected" parameter="zoom_in" />
<on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
</menu_item_call>
<menu_item_call <menu_item_call
label="Map" label="Map"
layout="topleft" layout="topleft"

View File

@ -49,6 +49,13 @@
</menu_item_call> </menu_item_call>
<menu_item_separator <menu_item_separator
layout="topleft"/> layout="topleft"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<on_click function="Avatar.DoToSelected" parameter="zoom_in" />
<on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
</menu_item_call>
<menu_item_call <menu_item_call
label="Map" label="Map"
layout="topleft" layout="topleft"

View File

@ -24,4 +24,22 @@
function="ObjectIcon.Action" function="ObjectIcon.Action"
parameter="block" /> parameter="block" />
</menu_item_call> </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
label="Show on Map"
layout="topleft"
name="show_on_map">
<menu_item_call.on_click
function="ObjectIcon.Action"
parameter="map" />
</menu_item_call>
<menu_item_call
label="Teleport to Object Location"
layout="topleft"
name="teleport_to_object">
<menu_item_call.on_click
function="ObjectIcon.Action"
parameter="teleport" />
</menu_item_call>
</menu> </menu>

View File

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu <context_menu
layout="topleft" layout="topleft"
name="Avatar Context Menu"> name="Nearby People Context Menu">
<menu_item_call <menu_item_call
label="View Profile" label="View Profile"
layout="topleft" layout="topleft"
name="View Profile"> name="view_profile">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.Profile" /> function="Avatar.Profile" />
</menu_item_call> </menu_item_call>
<menu_item_call <menu_item_call
label="IM" label="IM"
layout="topleft" layout="topleft"
name="IM"> name="im">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.IM" /> function="Avatar.IM" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -21,7 +21,7 @@
</menu_item_call> </menu_item_call>
<menu_item_call <menu_item_call
label="Offer Teleport" label="Offer Teleport"
name="teleport"> name="offer_teleport">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.OfferTeleport"/> function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable <menu_item_call.on_enable
@ -31,7 +31,7 @@
<menu_item_call <menu_item_call
label="Voice call" label="Voice call"
layout="topleft" layout="topleft"
name="Call"> name="voice_call">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.Call" /> function="Avatar.Call" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -42,18 +42,18 @@
<menu_item_call <menu_item_call
label="View chat history..." label="View chat history..."
layout="topleft" layout="topleft"
name="Chat history"> name="chat_history">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.Calllog" /> function="Avatar.Calllog" />
<menu_item_call.on_enable <menu_item_call.on_enable
function="Avatar.EnableItem" function="Avatar.EnableItem"
parameter="can_callog"/> parameter="can_callog"/>
</menu_item_call> </menu_item_call>
<menu_item_separator /> <menu_item_separator name="separator_chat_history"/>
<menu_item_call <menu_item_call
label="Add Friend" label="Add Friend"
layout="topleft" layout="topleft"
name="Add Friend"> name="add_friend">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.AddFriend" /> function="Avatar.AddFriend" />
<menu_item_call.on_visible <menu_item_call.on_visible
@ -63,7 +63,7 @@
<menu_item_call <menu_item_call
label="Remove Friend" label="Remove Friend"
layout="topleft" layout="topleft"
name="Remove Friend"> name="remove_friend">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.RemoveFriend" /> function="Avatar.RemoveFriend" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -73,18 +73,28 @@
<menu_item_call <menu_item_call
label="Invite to group..." label="Invite to group..."
layout="topleft" layout="topleft"
name="Invite"> name="invite_to_group">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.InviteToGroup" /> function="Avatar.InviteToGroup" />
<menu_item_call.on_enable <menu_item_call.on_enable
function="Avatar.EnableItem" function="Avatar.EnableItem"
parameter="can_invite"/> parameter="can_invite"/>
</menu_item_call> </menu_item_call>
<menu_item_separator /> <menu_item_separator name="separator_invite_to_group"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<menu_item_call.on_click
function="Avatar.ZoomIn" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_zoom_in"/>
</menu_item_call>
<menu_item_call <menu_item_call
label="Map" label="Map"
layout="topleft" layout="topleft"
name="Map"> name="map">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.ShowOnMap" /> function="Avatar.ShowOnMap" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -94,7 +104,7 @@
<menu_item_call <menu_item_call
label="Share" label="Share"
layout="topleft" layout="topleft"
name="Share"> name="share">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.Share" /> function="Avatar.Share" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -104,7 +114,7 @@
<menu_item_call <menu_item_call
label="Pay" label="Pay"
layout="topleft" layout="topleft"
name="Pay"> name="pay">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.Pay" /> function="Avatar.Pay" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -114,7 +124,7 @@
<menu_item_check <menu_item_check
label="Block/Unblock" label="Block/Unblock"
layout="topleft" layout="topleft"
name="Block/Unblock"> name="block_unblock">
<menu_item_check.on_click <menu_item_check.on_click
function="Avatar.BlockUnblock" /> function="Avatar.BlockUnblock" />
<menu_item_check.on_check <menu_item_check.on_check

View File

@ -6,7 +6,7 @@
enabled="false" enabled="false"
label="Add Friends" label="Add Friends"
layout="topleft" layout="topleft"
name="Add Friends"> name="add_friends">
<on_click <on_click
function="Avatar.AddFriends" /> function="Avatar.AddFriends" />
<on_enable <on_enable
@ -16,7 +16,7 @@
<menu_item_call <menu_item_call
label="Remove Friends" label="Remove Friends"
layout="topleft" layout="topleft"
name="Remove Friend"> name="remove_friends">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.RemoveFriend" /> function="Avatar.RemoveFriend" />
<menu_item_call.on_enable <menu_item_call.on_enable
@ -26,7 +26,7 @@
<menu_item_call <menu_item_call
label="IM" label="IM"
layout="topleft" layout="topleft"
name="IM"> name="im">
<on_click <on_click
function="Avatar.IM" /> function="Avatar.IM" />
</menu_item_call> </menu_item_call>
@ -34,7 +34,7 @@
enabled="false" enabled="false"
label="Call" label="Call"
layout="topleft" layout="topleft"
name="Call"> name="call">
<on_click <on_click
function="Avatar.Call" /> function="Avatar.Call" />
<on_enable <on_enable
@ -45,7 +45,7 @@
enabled="false" enabled="false"
label="Share" label="Share"
layout="topleft" layout="topleft"
name="Share"> name="share">
<on_click <on_click
function="Avatar.Share" /> function="Avatar.Share" />
</menu_item_call> </menu_item_call>
@ -53,13 +53,13 @@
enabled="false" enabled="false"
label="Pay" label="Pay"
layout="topleft" layout="topleft"
name="Pay"> name="pay">
<on_click <on_click
function="Avatar.Pay" /> function="Avatar.Pay" />
</menu_item_call> </menu_item_call>
<menu_item_call <menu_item_call
label="Offer Teleport" label="Offer Teleport"
name="teleport"> name="offer_teleport">
<menu_item_call.on_click <menu_item_call.on_click
function="Avatar.OfferTeleport"/> function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable <menu_item_call.on_enable

View File

@ -1,20 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu <context_menu
layout="topleft" layout="topleft"
name="Url Popup"> name="Url Popup">
<menu_item_call <menu_item_call
label="Send IM" label="View Profile"
layout="topleft" layout="topleft"
name="show_agent"> name="show_agent">
<menu_item_call.on_click
function="Url.ShowProfile" />
</menu_item_call>
<menu_item_call
label="Send IM..."
layout="topleft"
name="send_im">
<menu_item_call.on_click <menu_item_call.on_click
function="Url.SendIM" /> function="Url.SendIM" />
</menu_item_call> </menu_item_call>
<menu_item_call <menu_item_call
label="Show Resident Profile" label="Add Friend..."
layout="topleft" layout="topleft"
name="show_agent"> name="add_friend">
<menu_item_call.on_click <menu_item_call.on_click
function="Url.ShowProfile" /> function="Url.AddFriend" />
</menu_item_call> </menu_item_call>
<menu_item_separator <menu_item_separator
layout="topleft" /> layout="topleft" />

View File

@ -7,7 +7,7 @@
layout="topleft" layout="topleft"
name="show_group"> name="show_group">
<menu_item_call.on_click <menu_item_call.on_click
function="Url.Execute" /> function="Url.ShowProfile" />
</menu_item_call> </menu_item_call>
<menu_item_separator <menu_item_separator
layout="topleft" /> layout="topleft" />

View File

@ -3,7 +3,7 @@
layout="topleft" layout="topleft"
name="Url Popup"> name="Url Popup">
<menu_item_call <menu_item_call
label="Show Object Information" label="Object Profile..."
layout="topleft" layout="topleft"
name="show_object"> name="show_object">
<menu_item_call.on_click <menu_item_call.on_click

View File

@ -9998,7 +9998,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga" icon="alertmodal.tga"
name="PreferenceChatClearLog" name="PreferenceChatClearLog"
type="alertmodal"> type="alertmodal">
This will delete the log of previous conversations. Proceed? This will delete the logs of previous conversations, and any backups of that file.
<tag>confirm</tag> <tag>confirm</tag>
<usetemplate <usetemplate
ignoretext="Confirm before I delete the log of previous conversations." ignoretext="Confirm before I delete the log of previous conversations."
@ -10011,7 +10011,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga" icon="alertmodal.tga"
name="PreferenceChatDeleteTranscripts" name="PreferenceChatDeleteTranscripts"
type="alertmodal"> type="alertmodal">
This will delete transcripts for all previous conversations. The list of conversations will not be affected. If you run scripts on your chat transcript files, you may want to proceed with caution. Proceed? This will delete the transcripts for all previous conversations. The list of past conversations will not be affected. All files with the suffixes .txt and txt.backup in the folder [FOLDER] will be deleted.
<tag>confirm</tag> <tag>confirm</tag>
<usetemplate <usetemplate
ignoretext="Confirm before I delete transcripts." ignoretext="Confirm before I delete transcripts."

View File

@ -429,7 +429,6 @@
</text> </text>
<line_editor <line_editor
enabled="false"
control_name="InstantMessageLogPath" control_name="InstantMessageLogPath"
border_style="line" border_style="line"
border_thickness="1" border_thickness="1"