diff --git a/res/drawable-hdpi/ic_add_caption.png b/res/drawable-hdpi/ic_add_caption.png
deleted file mode 100644
index 92cdffc7da..0000000000
Binary files a/res/drawable-hdpi/ic_add_caption.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_add_caption_36.png b/res/drawable-hdpi/ic_add_caption_36.png
new file mode 100644
index 0000000000..3aa8cfb0f2
Binary files /dev/null and b/res/drawable-hdpi/ic_add_caption_36.png differ
diff --git a/res/drawable-hdpi/ic_camera_filled_24.png b/res/drawable-hdpi/ic_camera_filled_24.png
new file mode 100644
index 0000000000..9dd7a84582
Binary files /dev/null and b/res/drawable-hdpi/ic_camera_filled_24.png differ
diff --git a/res/drawable-hdpi/ic_camera_front.png b/res/drawable-hdpi/ic_camera_front.png
deleted file mode 100644
index 4895cfc794..0000000000
Binary files a/res/drawable-hdpi/ic_camera_front.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_camera_rear.png b/res/drawable-hdpi/ic_camera_rear.png
deleted file mode 100644
index befb6e2fd7..0000000000
Binary files a/res/drawable-hdpi/ic_camera_rear.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_caption.png b/res/drawable-hdpi/ic_caption.png
deleted file mode 100644
index d63dfa1d27..0000000000
Binary files a/res/drawable-hdpi/ic_caption.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_caption_28.png b/res/drawable-hdpi/ic_caption_28.png
new file mode 100644
index 0000000000..04931524f8
Binary files /dev/null and b/res/drawable-hdpi/ic_caption_28.png differ
diff --git a/res/drawable-hdpi/ic_check_circle_filled_36.png b/res/drawable-hdpi/ic_check_circle_filled_36.png
new file mode 100644
index 0000000000..e00b6b5674
Binary files /dev/null and b/res/drawable-hdpi/ic_check_circle_filled_36.png differ
diff --git a/res/drawable-hdpi/ic_create_album_filled_32.png b/res/drawable-hdpi/ic_create_album_filled_32.png
new file mode 100644
index 0000000000..fc6159d9ce
Binary files /dev/null and b/res/drawable-hdpi/ic_create_album_filled_32.png differ
diff --git a/res/drawable-hdpi/ic_create_album_outline_32.png b/res/drawable-hdpi/ic_create_album_outline_32.png
new file mode 100644
index 0000000000..7f5da89160
Binary files /dev/null and b/res/drawable-hdpi/ic_create_album_outline_32.png differ
diff --git a/res/drawable-hdpi/ic_marker_36.png b/res/drawable-hdpi/ic_marker_36.png
new file mode 100644
index 0000000000..dde1357bcb
Binary files /dev/null and b/res/drawable-hdpi/ic_marker_36.png differ
diff --git a/res/drawable-hdpi/ic_plus_28.png b/res/drawable-hdpi/ic_plus_28.png
new file mode 100644
index 0000000000..b23db3489e
Binary files /dev/null and b/res/drawable-hdpi/ic_plus_28.png differ
diff --git a/res/drawable-hdpi/ic_scribble_brush.png b/res/drawable-hdpi/ic_scribble_brush.png
deleted file mode 100644
index 6c31c106a3..0000000000
Binary files a/res/drawable-hdpi/ic_scribble_brush.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_scribble_delete.png b/res/drawable-hdpi/ic_scribble_delete.png
deleted file mode 100644
index 582e992320..0000000000
Binary files a/res/drawable-hdpi/ic_scribble_delete.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_scribble_text.png b/res/drawable-hdpi/ic_scribble_text.png
deleted file mode 100644
index 21e335c99c..0000000000
Binary files a/res/drawable-hdpi/ic_scribble_text.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_scribble_undo.png b/res/drawable-hdpi/ic_scribble_undo.png
deleted file mode 100644
index 693cde60d2..0000000000
Binary files a/res/drawable-hdpi/ic_scribble_undo.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_switch_camera_36.png b/res/drawable-hdpi/ic_switch_camera_36.png
new file mode 100644
index 0000000000..a09cb92cc2
Binary files /dev/null and b/res/drawable-hdpi/ic_switch_camera_36.png differ
diff --git a/res/drawable-hdpi/ic_text_36.png b/res/drawable-hdpi/ic_text_36.png
new file mode 100644
index 0000000000..5ad62dacec
Binary files /dev/null and b/res/drawable-hdpi/ic_text_36.png differ
diff --git a/res/drawable-hdpi/ic_trash_outline_36.png b/res/drawable-hdpi/ic_trash_outline_36.png
new file mode 100644
index 0000000000..0cc7d2bd50
Binary files /dev/null and b/res/drawable-hdpi/ic_trash_outline_36.png differ
diff --git a/res/drawable-hdpi/ic_undo_36.png b/res/drawable-hdpi/ic_undo_36.png
new file mode 100644
index 0000000000..6b5ff3ee69
Binary files /dev/null and b/res/drawable-hdpi/ic_undo_36.png differ
diff --git a/res/drawable-hdpi/ic_x_28.png b/res/drawable-hdpi/ic_x_28.png
new file mode 100644
index 0000000000..e2f4911569
Binary files /dev/null and b/res/drawable-hdpi/ic_x_28.png differ
diff --git a/res/drawable-mdpi/ic_add_caption.png b/res/drawable-mdpi/ic_add_caption.png
deleted file mode 100644
index a80b6cf503..0000000000
Binary files a/res/drawable-mdpi/ic_add_caption.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_add_caption_36.png b/res/drawable-mdpi/ic_add_caption_36.png
new file mode 100644
index 0000000000..f7f08d5de4
Binary files /dev/null and b/res/drawable-mdpi/ic_add_caption_36.png differ
diff --git a/res/drawable-mdpi/ic_camera_filled_24.png b/res/drawable-mdpi/ic_camera_filled_24.png
new file mode 100644
index 0000000000..fa5b99e7bf
Binary files /dev/null and b/res/drawable-mdpi/ic_camera_filled_24.png differ
diff --git a/res/drawable-mdpi/ic_camera_front.png b/res/drawable-mdpi/ic_camera_front.png
deleted file mode 100644
index dcad59568c..0000000000
Binary files a/res/drawable-mdpi/ic_camera_front.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_camera_rear.png b/res/drawable-mdpi/ic_camera_rear.png
deleted file mode 100644
index b124675c98..0000000000
Binary files a/res/drawable-mdpi/ic_camera_rear.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_caption.png b/res/drawable-mdpi/ic_caption.png
deleted file mode 100644
index bc2a88f747..0000000000
Binary files a/res/drawable-mdpi/ic_caption.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_caption_28.png b/res/drawable-mdpi/ic_caption_28.png
new file mode 100644
index 0000000000..bfb1305411
Binary files /dev/null and b/res/drawable-mdpi/ic_caption_28.png differ
diff --git a/res/drawable-mdpi/ic_check_circle_filled_36.png b/res/drawable-mdpi/ic_check_circle_filled_36.png
new file mode 100644
index 0000000000..0063fcdf6e
Binary files /dev/null and b/res/drawable-mdpi/ic_check_circle_filled_36.png differ
diff --git a/res/drawable-mdpi/ic_create_album_filled_32.png b/res/drawable-mdpi/ic_create_album_filled_32.png
new file mode 100644
index 0000000000..db1838faca
Binary files /dev/null and b/res/drawable-mdpi/ic_create_album_filled_32.png differ
diff --git a/res/drawable-mdpi/ic_create_album_outline_32.png b/res/drawable-mdpi/ic_create_album_outline_32.png
new file mode 100644
index 0000000000..52ac25a099
Binary files /dev/null and b/res/drawable-mdpi/ic_create_album_outline_32.png differ
diff --git a/res/drawable-mdpi/ic_marker_36.png b/res/drawable-mdpi/ic_marker_36.png
new file mode 100644
index 0000000000..89fe303da4
Binary files /dev/null and b/res/drawable-mdpi/ic_marker_36.png differ
diff --git a/res/drawable-mdpi/ic_plus_28.png b/res/drawable-mdpi/ic_plus_28.png
new file mode 100644
index 0000000000..20028b9af5
Binary files /dev/null and b/res/drawable-mdpi/ic_plus_28.png differ
diff --git a/res/drawable-mdpi/ic_scribble_brush.png b/res/drawable-mdpi/ic_scribble_brush.png
deleted file mode 100644
index fca4db97af..0000000000
Binary files a/res/drawable-mdpi/ic_scribble_brush.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_scribble_delete.png b/res/drawable-mdpi/ic_scribble_delete.png
deleted file mode 100644
index 367b6bb696..0000000000
Binary files a/res/drawable-mdpi/ic_scribble_delete.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_scribble_text.png b/res/drawable-mdpi/ic_scribble_text.png
deleted file mode 100644
index e116229292..0000000000
Binary files a/res/drawable-mdpi/ic_scribble_text.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_scribble_undo.png b/res/drawable-mdpi/ic_scribble_undo.png
deleted file mode 100644
index 2cef26a92d..0000000000
Binary files a/res/drawable-mdpi/ic_scribble_undo.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_switch_camera_36.png b/res/drawable-mdpi/ic_switch_camera_36.png
new file mode 100644
index 0000000000..f402ca9bdc
Binary files /dev/null and b/res/drawable-mdpi/ic_switch_camera_36.png differ
diff --git a/res/drawable-mdpi/ic_text_36.png b/res/drawable-mdpi/ic_text_36.png
new file mode 100644
index 0000000000..5f04230da2
Binary files /dev/null and b/res/drawable-mdpi/ic_text_36.png differ
diff --git a/res/drawable-mdpi/ic_trash_outline_36.png b/res/drawable-mdpi/ic_trash_outline_36.png
new file mode 100644
index 0000000000..e14b9b2eea
Binary files /dev/null and b/res/drawable-mdpi/ic_trash_outline_36.png differ
diff --git a/res/drawable-mdpi/ic_undo_36.png b/res/drawable-mdpi/ic_undo_36.png
new file mode 100644
index 0000000000..5e76ac0333
Binary files /dev/null and b/res/drawable-mdpi/ic_undo_36.png differ
diff --git a/res/drawable-mdpi/ic_x_28.png b/res/drawable-mdpi/ic_x_28.png
new file mode 100644
index 0000000000..b02b88e2ca
Binary files /dev/null and b/res/drawable-mdpi/ic_x_28.png differ
diff --git a/res/drawable-v21/media_camera_button_background.xml b/res/drawable-v21/media_camera_button_background.xml
new file mode 100644
index 0000000000..21a75a84d1
--- /dev/null
+++ b/res/drawable-v21/media_camera_button_background.xml
@@ -0,0 +1,16 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable-v21/mediarail_button_background.xml b/res/drawable-v21/mediarail_button_background.xml
new file mode 100644
index 0000000000..035512fbff
--- /dev/null
+++ b/res/drawable-v21/mediarail_button_background.xml
@@ -0,0 +1,19 @@
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/res/drawable-xhdpi/ic_add_caption.png b/res/drawable-xhdpi/ic_add_caption.png
deleted file mode 100644
index 0bf6f3552f..0000000000
Binary files a/res/drawable-xhdpi/ic_add_caption.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_add_caption_36.png b/res/drawable-xhdpi/ic_add_caption_36.png
new file mode 100644
index 0000000000..7d6a2c322f
Binary files /dev/null and b/res/drawable-xhdpi/ic_add_caption_36.png differ
diff --git a/res/drawable-xhdpi/ic_camera_filled_24.png b/res/drawable-xhdpi/ic_camera_filled_24.png
new file mode 100644
index 0000000000..f91cf25d89
Binary files /dev/null and b/res/drawable-xhdpi/ic_camera_filled_24.png differ
diff --git a/res/drawable-xhdpi/ic_camera_front.png b/res/drawable-xhdpi/ic_camera_front.png
deleted file mode 100644
index f8143b9942..0000000000
Binary files a/res/drawable-xhdpi/ic_camera_front.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_camera_rear.png b/res/drawable-xhdpi/ic_camera_rear.png
deleted file mode 100644
index 5e64fdbbee..0000000000
Binary files a/res/drawable-xhdpi/ic_camera_rear.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_caption.png b/res/drawable-xhdpi/ic_caption.png
deleted file mode 100644
index 48d0d69c55..0000000000
Binary files a/res/drawable-xhdpi/ic_caption.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_caption_28.png b/res/drawable-xhdpi/ic_caption_28.png
new file mode 100644
index 0000000000..eeba8d5ca4
Binary files /dev/null and b/res/drawable-xhdpi/ic_caption_28.png differ
diff --git a/res/drawable-xhdpi/ic_check_circle_filled_36.png b/res/drawable-xhdpi/ic_check_circle_filled_36.png
new file mode 100644
index 0000000000..625c7e9011
Binary files /dev/null and b/res/drawable-xhdpi/ic_check_circle_filled_36.png differ
diff --git a/res/drawable-xhdpi/ic_create_album_filled_32.png b/res/drawable-xhdpi/ic_create_album_filled_32.png
new file mode 100644
index 0000000000..142ba5ccff
Binary files /dev/null and b/res/drawable-xhdpi/ic_create_album_filled_32.png differ
diff --git a/res/drawable-xhdpi/ic_create_album_outline_32.png b/res/drawable-xhdpi/ic_create_album_outline_32.png
new file mode 100644
index 0000000000..901e33cc20
Binary files /dev/null and b/res/drawable-xhdpi/ic_create_album_outline_32.png differ
diff --git a/res/drawable-xhdpi/ic_marker_36.png b/res/drawable-xhdpi/ic_marker_36.png
new file mode 100644
index 0000000000..cff3107234
Binary files /dev/null and b/res/drawable-xhdpi/ic_marker_36.png differ
diff --git a/res/drawable-xhdpi/ic_plus_28.png b/res/drawable-xhdpi/ic_plus_28.png
new file mode 100644
index 0000000000..362b614b5f
Binary files /dev/null and b/res/drawable-xhdpi/ic_plus_28.png differ
diff --git a/res/drawable-xhdpi/ic_scribble_brush.png b/res/drawable-xhdpi/ic_scribble_brush.png
deleted file mode 100644
index 6dba282c76..0000000000
Binary files a/res/drawable-xhdpi/ic_scribble_brush.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_scribble_delete.png b/res/drawable-xhdpi/ic_scribble_delete.png
deleted file mode 100644
index fc229e0724..0000000000
Binary files a/res/drawable-xhdpi/ic_scribble_delete.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_scribble_text.png b/res/drawable-xhdpi/ic_scribble_text.png
deleted file mode 100644
index e30129ba63..0000000000
Binary files a/res/drawable-xhdpi/ic_scribble_text.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_scribble_undo.png b/res/drawable-xhdpi/ic_scribble_undo.png
deleted file mode 100644
index b74a133d54..0000000000
Binary files a/res/drawable-xhdpi/ic_scribble_undo.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_switch_camera_36.png b/res/drawable-xhdpi/ic_switch_camera_36.png
new file mode 100644
index 0000000000..9d80ebc202
Binary files /dev/null and b/res/drawable-xhdpi/ic_switch_camera_36.png differ
diff --git a/res/drawable-xhdpi/ic_text_36.png b/res/drawable-xhdpi/ic_text_36.png
new file mode 100644
index 0000000000..b9bbe7fdd0
Binary files /dev/null and b/res/drawable-xhdpi/ic_text_36.png differ
diff --git a/res/drawable-xhdpi/ic_trash_outline_36.png b/res/drawable-xhdpi/ic_trash_outline_36.png
new file mode 100644
index 0000000000..1721c329a4
Binary files /dev/null and b/res/drawable-xhdpi/ic_trash_outline_36.png differ
diff --git a/res/drawable-xhdpi/ic_undo_36.png b/res/drawable-xhdpi/ic_undo_36.png
new file mode 100644
index 0000000000..8d173d16ea
Binary files /dev/null and b/res/drawable-xhdpi/ic_undo_36.png differ
diff --git a/res/drawable-xhdpi/ic_x_28.png b/res/drawable-xhdpi/ic_x_28.png
new file mode 100644
index 0000000000..539ee4ad7f
Binary files /dev/null and b/res/drawable-xhdpi/ic_x_28.png differ
diff --git a/res/drawable-xxhdpi/ic_add_caption.png b/res/drawable-xxhdpi/ic_add_caption.png
deleted file mode 100644
index d423e74e3c..0000000000
Binary files a/res/drawable-xxhdpi/ic_add_caption.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_add_caption_36.png b/res/drawable-xxhdpi/ic_add_caption_36.png
new file mode 100644
index 0000000000..1136f4a20a
Binary files /dev/null and b/res/drawable-xxhdpi/ic_add_caption_36.png differ
diff --git a/res/drawable-xxhdpi/ic_camera_filled_24.png b/res/drawable-xxhdpi/ic_camera_filled_24.png
new file mode 100644
index 0000000000..2fbd146470
Binary files /dev/null and b/res/drawable-xxhdpi/ic_camera_filled_24.png differ
diff --git a/res/drawable-xxhdpi/ic_camera_front.png b/res/drawable-xxhdpi/ic_camera_front.png
deleted file mode 100644
index b053de97ed..0000000000
Binary files a/res/drawable-xxhdpi/ic_camera_front.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_camera_rear.png b/res/drawable-xxhdpi/ic_camera_rear.png
deleted file mode 100644
index 788e621db7..0000000000
Binary files a/res/drawable-xxhdpi/ic_camera_rear.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_caption.png b/res/drawable-xxhdpi/ic_caption.png
deleted file mode 100644
index 6892ef867c..0000000000
Binary files a/res/drawable-xxhdpi/ic_caption.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_caption_28.png b/res/drawable-xxhdpi/ic_caption_28.png
new file mode 100644
index 0000000000..885fa26c3a
Binary files /dev/null and b/res/drawable-xxhdpi/ic_caption_28.png differ
diff --git a/res/drawable-xxhdpi/ic_check_circle_filled_36.png b/res/drawable-xxhdpi/ic_check_circle_filled_36.png
new file mode 100644
index 0000000000..69c728f056
Binary files /dev/null and b/res/drawable-xxhdpi/ic_check_circle_filled_36.png differ
diff --git a/res/drawable-xxhdpi/ic_create_album_filled_32.png b/res/drawable-xxhdpi/ic_create_album_filled_32.png
new file mode 100644
index 0000000000..5aef02de30
Binary files /dev/null and b/res/drawable-xxhdpi/ic_create_album_filled_32.png differ
diff --git a/res/drawable-xxhdpi/ic_create_album_outline_32.png b/res/drawable-xxhdpi/ic_create_album_outline_32.png
new file mode 100644
index 0000000000..2e675e3b39
Binary files /dev/null and b/res/drawable-xxhdpi/ic_create_album_outline_32.png differ
diff --git a/res/drawable-xxhdpi/ic_marker_36.png b/res/drawable-xxhdpi/ic_marker_36.png
new file mode 100644
index 0000000000..388479091c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_marker_36.png differ
diff --git a/res/drawable-xxhdpi/ic_plus_28.png b/res/drawable-xxhdpi/ic_plus_28.png
new file mode 100644
index 0000000000..e09c7ae8c2
Binary files /dev/null and b/res/drawable-xxhdpi/ic_plus_28.png differ
diff --git a/res/drawable-xxhdpi/ic_scribble_brush.png b/res/drawable-xxhdpi/ic_scribble_brush.png
deleted file mode 100644
index 10c37572ce..0000000000
Binary files a/res/drawable-xxhdpi/ic_scribble_brush.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_scribble_delete.png b/res/drawable-xxhdpi/ic_scribble_delete.png
deleted file mode 100644
index f127ff2c6d..0000000000
Binary files a/res/drawable-xxhdpi/ic_scribble_delete.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_scribble_text.png b/res/drawable-xxhdpi/ic_scribble_text.png
deleted file mode 100644
index 7b091c9bac..0000000000
Binary files a/res/drawable-xxhdpi/ic_scribble_text.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_scribble_undo.png b/res/drawable-xxhdpi/ic_scribble_undo.png
deleted file mode 100644
index 6ffae6f213..0000000000
Binary files a/res/drawable-xxhdpi/ic_scribble_undo.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_switch_camera_36.png b/res/drawable-xxhdpi/ic_switch_camera_36.png
new file mode 100644
index 0000000000..b4b34852da
Binary files /dev/null and b/res/drawable-xxhdpi/ic_switch_camera_36.png differ
diff --git a/res/drawable-xxhdpi/ic_text_36.png b/res/drawable-xxhdpi/ic_text_36.png
new file mode 100644
index 0000000000..22cbfb82ec
Binary files /dev/null and b/res/drawable-xxhdpi/ic_text_36.png differ
diff --git a/res/drawable-xxhdpi/ic_trash_outline_36.png b/res/drawable-xxhdpi/ic_trash_outline_36.png
new file mode 100644
index 0000000000..2688b6cf5c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_trash_outline_36.png differ
diff --git a/res/drawable-xxhdpi/ic_undo_36.png b/res/drawable-xxhdpi/ic_undo_36.png
new file mode 100644
index 0000000000..b5877cfcb5
Binary files /dev/null and b/res/drawable-xxhdpi/ic_undo_36.png differ
diff --git a/res/drawable-xxhdpi/ic_x_28.png b/res/drawable-xxhdpi/ic_x_28.png
new file mode 100644
index 0000000000..14fc11201a
Binary files /dev/null and b/res/drawable-xxhdpi/ic_x_28.png differ
diff --git a/res/drawable-xxxhdpi/ic_add_caption.png b/res/drawable-xxxhdpi/ic_add_caption.png
deleted file mode 100644
index cb17f42275..0000000000
Binary files a/res/drawable-xxxhdpi/ic_add_caption.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_add_caption_36.png b/res/drawable-xxxhdpi/ic_add_caption_36.png
new file mode 100644
index 0000000000..89052339c7
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_add_caption_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_camera_filled_24.png b/res/drawable-xxxhdpi/ic_camera_filled_24.png
new file mode 100644
index 0000000000..0f54e607a3
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_camera_filled_24.png differ
diff --git a/res/drawable-xxxhdpi/ic_camera_front.png b/res/drawable-xxxhdpi/ic_camera_front.png
deleted file mode 100644
index 69726bd2fe..0000000000
Binary files a/res/drawable-xxxhdpi/ic_camera_front.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_camera_rear.png b/res/drawable-xxxhdpi/ic_camera_rear.png
deleted file mode 100644
index 7ec77723b3..0000000000
Binary files a/res/drawable-xxxhdpi/ic_camera_rear.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_caption.png b/res/drawable-xxxhdpi/ic_caption.png
deleted file mode 100644
index 5ce643d2d1..0000000000
Binary files a/res/drawable-xxxhdpi/ic_caption.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_caption_28.png b/res/drawable-xxxhdpi/ic_caption_28.png
new file mode 100644
index 0000000000..3d4b47158b
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_caption_28.png differ
diff --git a/res/drawable-xxxhdpi/ic_check_circle_filled_36.png b/res/drawable-xxxhdpi/ic_check_circle_filled_36.png
new file mode 100644
index 0000000000..2edd336b38
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_check_circle_filled_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_create_album_filled_32.png b/res/drawable-xxxhdpi/ic_create_album_filled_32.png
new file mode 100644
index 0000000000..7431841200
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_create_album_filled_32.png differ
diff --git a/res/drawable-xxxhdpi/ic_create_album_outline_32.png b/res/drawable-xxxhdpi/ic_create_album_outline_32.png
new file mode 100644
index 0000000000..63ccb10945
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_create_album_outline_32.png differ
diff --git a/res/drawable-xxxhdpi/ic_marker_36.png b/res/drawable-xxxhdpi/ic_marker_36.png
new file mode 100644
index 0000000000..529b07b71b
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_marker_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_scribble_brush.png b/res/drawable-xxxhdpi/ic_scribble_brush.png
deleted file mode 100644
index 38e12c3284..0000000000
Binary files a/res/drawable-xxxhdpi/ic_scribble_brush.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_scribble_delete.png b/res/drawable-xxxhdpi/ic_scribble_delete.png
deleted file mode 100644
index 53dcb4fdaf..0000000000
Binary files a/res/drawable-xxxhdpi/ic_scribble_delete.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_scribble_text.png b/res/drawable-xxxhdpi/ic_scribble_text.png
deleted file mode 100644
index 001428bfa7..0000000000
Binary files a/res/drawable-xxxhdpi/ic_scribble_text.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_scribble_undo.png b/res/drawable-xxxhdpi/ic_scribble_undo.png
deleted file mode 100644
index b3b526b2ec..0000000000
Binary files a/res/drawable-xxxhdpi/ic_scribble_undo.png and /dev/null differ
diff --git a/res/drawable-xxxhdpi/ic_switch_camera_36.png b/res/drawable-xxxhdpi/ic_switch_camera_36.png
new file mode 100644
index 0000000000..30fec8d532
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_switch_camera_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_text_36.png b/res/drawable-xxxhdpi/ic_text_36.png
new file mode 100644
index 0000000000..b1f4eed532
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_text_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_trash_outline_36.png b/res/drawable-xxxhdpi/ic_trash_outline_36.png
new file mode 100644
index 0000000000..2fccd17e7a
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_trash_outline_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_undo_36.png b/res/drawable-xxxhdpi/ic_undo_36.png
new file mode 100644
index 0000000000..44300d0f54
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_undo_36.png differ
diff --git a/res/drawable-xxxhdpi/ic_x_28.png b/res/drawable-xxxhdpi/ic_x_28.png
new file mode 100644
index 0000000000..907056a5af
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_x_28.png differ
diff --git a/res/drawable/compose_background_camera.xml b/res/drawable/compose_background_camera.xml
index cfb74f334c..e9b6aa6954 100644
--- a/res/drawable/compose_background_camera.xml
+++ b/res/drawable/compose_background_camera.xml
@@ -5,10 +5,7 @@
-
-
+ android:color="@color/core_white" />
diff --git a/res/drawable/media_camera_button_background.xml b/res/drawable/media_camera_button_background.xml
new file mode 100644
index 0000000000..d928269be8
--- /dev/null
+++ b/res/drawable/media_camera_button_background.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/mediapicker_item_border_dark.xml b/res/drawable/mediapicker_item_border_dark.xml
index d77188b203..4b5741d8ec 100644
--- a/res/drawable/mediapicker_item_border_dark.xml
+++ b/res/drawable/mediapicker_item_border_dark.xml
@@ -3,6 +3,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
+
+
diff --git a/res/drawable/media_rail_item_background.xml b/res/drawable/mediarail_button_background.xml
similarity index 60%
rename from res/drawable/media_rail_item_background.xml
rename to res/drawable/mediarail_button_background.xml
index f9cceab4f7..09e616ea41 100644
--- a/res/drawable/media_rail_item_background.xml
+++ b/res/drawable/mediarail_button_background.xml
@@ -1,4 +1,5 @@
-
+
+
\ No newline at end of file
diff --git a/res/drawable/mediarail_media_outline.xml b/res/drawable/mediarail_media_outline.xml
new file mode 100644
index 0000000000..8b6e4ec97f
--- /dev/null
+++ b/res/drawable/mediarail_media_outline.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/camera_controls_landscape.xml b/res/layout/camera_controls_landscape.xml
index d25e4ed499..4ed346376c 100644
--- a/res/layout/camera_controls_landscape.xml
+++ b/res/layout/camera_controls_landscape.xml
@@ -23,7 +23,7 @@
android:layout_above="@+id/camera_capture_button"
android:layout_marginBottom="40dp"
android:layout_centerHorizontal="true"
- android:src="@drawable/ic_camera_front"
+ android:src="@drawable/ic_switch_camera_36"
android:scaleType="fitCenter"
android:background="?selectableItemBackgroundBorderless"
android:visibility="gone"
diff --git a/res/layout/camera_controls_portrait.xml b/res/layout/camera_controls_portrait.xml
index 33fe8eda32..c1dc8cfdf0 100644
--- a/res/layout/camera_controls_portrait.xml
+++ b/res/layout/camera_controls_portrait.xml
@@ -24,7 +24,7 @@
android:layout_marginRight="40dp"
android:layout_marginEnd="40dp"
android:layout_centerVertical="true"
- android:src="@drawable/ic_camera_front"
+ android:src="@drawable/ic_switch_camera_36"
android:scaleType="fitCenter"
android:background="?selectableItemBackgroundBorderless"
android:visibility="gone"
diff --git a/res/layout/media_preview_album_rail_item.xml b/res/layout/media_preview_album_rail_item.xml
deleted file mode 100644
index 3ea969c611..0000000000
--- a/res/layout/media_preview_album_rail_item.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/mediarail_button_item.xml b/res/layout/mediarail_button_item.xml
new file mode 100644
index 0000000000..1cdf3e6ff7
--- /dev/null
+++ b/res/layout/mediarail_button_item.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/res/layout/mediarail_media_item.xml b/res/layout/mediarail_media_item.xml
new file mode 100644
index 0000000000..dd24845a57
--- /dev/null
+++ b/res/layout/mediarail_media_item.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/mediasend_activity.xml b/res/layout/mediasend_activity.xml
index f279426812..8285b524c1 100644
--- a/res/layout/mediasend_activity.xml
+++ b/res/layout/mediasend_activity.xml
@@ -51,4 +51,20 @@
+
+
\ No newline at end of file
diff --git a/res/layout/mediasend_fragment.xml b/res/layout/mediasend_fragment.xml
index c10b3ba854..acd59f951d 100644
--- a/res/layout/mediasend_fragment.xml
+++ b/res/layout/mediasend_fragment.xml
@@ -37,56 +37,41 @@
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
style="@style/Signal.Text.Body"
- android:paddingTop="11dp"
- android:paddingBottom="11dp"
- android:drawableLeft="@drawable/ic_add_caption"
- android:drawableStart="@drawable/ic_add_caption"
- android:drawablePadding="6dp"
android:maxLines="3"
android:maxLength="240"
android:hint="@string/MediaSendActivity_add_a_caption"
+ android:autoText="true"
+ android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
android:background="@null"/>
-
-
+ android:layout_marginBottom="12dp"
+ android:orientation="horizontal">
@@ -152,10 +137,9 @@
android:id="@+id/mediasend_characters_left"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="6dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
- android:paddingBottom="6dp"
+ android:paddingBottom="12dp"
android:visibility="gone"
tools:visibility="visible"
tools:text="160/160 (1)" />
@@ -171,13 +155,4 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/scribble_hud.xml b/res/layout/scribble_hud.xml
index c0e42990da..36f0f08996 100644
--- a/res/layout/scribble_hud.xml
+++ b/res/layout/scribble_hud.xml
@@ -9,95 +9,110 @@
tools:parentTag="android.widget.LinearLayout"
tools:background="@color/core_grey_60">
-
+ android:layout_weight="1"
+ android:animateLayoutChanges="true">
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
-
-
-
-
-
-
-
-
-
-
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="10dp"
+ android:layout_marginRight="10dp"
+ android:animateLayoutChanges="true"
+ android:orientation="horizontal"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="8dp"
+ android:src="@drawable/ic_trash_outline_36" />
-
-
-
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="8dp"
+ android:src="@drawable/ic_undo_36" />
+
+
+
+
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/mediapicker_multiselect.xml b/res/menu/mediapicker_multiselect.xml
index 5757848a4e..f5dbf2503a 100644
--- a/res/menu/mediapicker_multiselect.xml
+++ b/res/menu/mediapicker_multiselect.xml
@@ -1,10 +1,11 @@
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 422241e3cb..cb9392f697 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -2,4 +2,5 @@
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6128316348..24bf38bc3b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -462,15 +462,16 @@
Tap to select
-
- - You can\'t share more than %d item.
- - You can\'t share more than %d items.
-
Add a caption...
An item was removed because it exceeded the size limit
Camera unavailable.
+ Message to %s
+
+ - You can\'t share more than %d item.
+ - You can\'t share more than %d items.
+
All media
diff --git a/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java b/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java
index 9939da7db7..ba4ffb73d0 100644
--- a/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java
+++ b/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java
@@ -257,10 +257,10 @@ public class AttachmentTypeSelector extends PopupWindow {
private class RecentPhotoSelectedListener implements RecentPhotoViewRail.OnItemClickedListener {
@Override
- public void onItemClicked(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height) {
+ public void onItemClicked(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height, long size) {
animateWindowOutTranslate(getContentView());
- if (listener != null) listener.onQuickAttachment(uri, mimeType, bucketId, dateTaken, width, height);
+ if (listener != null) listener.onQuickAttachment(uri, mimeType, bucketId, dateTaken, width, height, size);
}
}
@@ -290,7 +290,7 @@ public class AttachmentTypeSelector extends PopupWindow {
public interface AttachmentClickedListener {
void onClick(int type);
- void onQuickAttachment(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height);
+ void onQuickAttachment(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height, long size);
}
}
diff --git a/src/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java b/src/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java
index 4414f3541a..cc218929e7 100644
--- a/src/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java
+++ b/src/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java
@@ -110,6 +110,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE));
String bucketId = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.BUCKET_ID));
int orientation = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION));
+ long size = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.SIZE));
int width = Build.VERSION.SDK_INT >= 16 ? cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation))) : 0;
int height = Build.VERSION.SDK_INT >= 16 ? cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation))) : 0;
@@ -124,7 +125,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
.into(viewHolder.imageView);
viewHolder.imageView.setOnClickListener(v -> {
- if (clickedListener != null) clickedListener.onItemClicked(uri, mimeType, bucketId, dateTaken, width, height);
+ if (clickedListener != null) clickedListener.onItemClicked(uri, mimeType, bucketId, dateTaken, width, height, size);
});
}
@@ -160,6 +161,6 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
}
public interface OnItemClickedListener {
- void onItemClicked(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height);
+ void onItemClicked(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height, long size);
}
}
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
index 8a91052937..62676446b7 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
@@ -2365,10 +2365,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
@Override
- public void onQuickAttachment(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height) {
+ public void onQuickAttachment(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height, long size) {
linkPreviewViewModel.onUserCancel();
- // TODO: Carry over size?
- Media media = new Media(uri, mimeType, dateTaken, width, height, 0, Optional.of(Media.ALL_MEDIA_BUCKET_ID), Optional.absent());
+ Media media = new Media(uri, mimeType, dateTaken, width, height, size, Optional.of(Media.ALL_MEDIA_BUCKET_ID), Optional.absent());
startActivityForResult(MediaSendActivity.buildEditorIntent(ConversationActivity.this, Collections.singletonList(media), recipient, composeText.getTextTrimmed(), sendButton.getSelectedTransport()), MEDIA_SENDER);
}
}
diff --git a/src/org/thoughtcrime/securesms/database/loaders/RecentPhotosLoader.java b/src/org/thoughtcrime/securesms/database/loaders/RecentPhotosLoader.java
index b539fc28b4..e8e2adde67 100644
--- a/src/org/thoughtcrime/securesms/database/loaders/RecentPhotosLoader.java
+++ b/src/org/thoughtcrime/securesms/database/loaders/RecentPhotosLoader.java
@@ -21,7 +21,8 @@ public class RecentPhotosLoader extends CursorLoader {
MediaStore.Images.ImageColumns.DATE_MODIFIED,
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.ImageColumns.MIME_TYPE,
- MediaStore.Images.ImageColumns.BUCKET_ID
+ MediaStore.Images.ImageColumns.BUCKET_ID,
+ MediaStore.Images.ImageColumns.SIZE
};
private static final String[] PROJECTION_16 = new String[] {
@@ -31,6 +32,7 @@ public class RecentPhotosLoader extends CursorLoader {
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.ImageColumns.MIME_TYPE,
MediaStore.Images.ImageColumns.BUCKET_ID,
+ MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.WIDTH,
MediaStore.Images.ImageColumns.HEIGHT
};
diff --git a/src/org/thoughtcrime/securesms/mediapreview/MediaRailAdapter.java b/src/org/thoughtcrime/securesms/mediapreview/MediaRailAdapter.java
index 11c6610883..78c06e045e 100644
--- a/src/org/thoughtcrime/securesms/mediapreview/MediaRailAdapter.java
+++ b/src/org/thoughtcrime/securesms/mediapreview/MediaRailAdapter.java
@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.mediapreview;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -8,6 +9,7 @@ import android.view.ViewGroup;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.ThumbnailView;
+import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.StableIdGenerator;
@@ -17,19 +19,23 @@ import java.util.List;
public class MediaRailAdapter extends RecyclerView.Adapter {
+ private static final int TYPE_MEDIA = 1;
+ private static final int TYPE_BUTTON = 2;
+
private final GlideRequests glideRequests;
private final List media;
private final RailItemListener listener;
- private final boolean deleteEnabled;
+ private final boolean editable;
private final StableIdGenerator stableIdGenerator;
+ private RailItemAddListener addListener;
private int activePosition;
- public MediaRailAdapter(@NonNull GlideRequests glideRequests, @NonNull RailItemListener listener, boolean deleteEnabled) {
+ public MediaRailAdapter(@NonNull GlideRequests glideRequests, @NonNull RailItemListener listener, boolean editable) {
this.glideRequests = glideRequests;
this.media = new ArrayList<>();
this.listener = listener;
- this.deleteEnabled = deleteEnabled;
+ this.editable = editable;
this.stableIdGenerator = new StableIdGenerator<>();
setHasStableIds(true);
@@ -37,13 +43,38 @@ public class MediaRailAdapter extends RecyclerView.Adapter media) {
@@ -79,25 +117,45 @@ public class MediaRailAdapter extends RecyclerView.Adapter railItemListener.onRailItemClicked(distanceFromActive));
- if (deleteEnabled && isActive) {
+ outline.setVisibility(isActive ? View.VISIBLE : View.GONE);
+
+ captionIndicator.setVisibility(media.getCaption().isPresent() ? View.VISIBLE : View.GONE);
+
+ if (editable && isActive) {
deleteButton.setVisibility(View.VISIBLE);
deleteButton.setOnClickListener(v -> railItemListener.onRailItemDeleteClicked(distanceFromActive));
} else {
@@ -111,8 +169,30 @@ public class MediaRailAdapter extends RecyclerView.Adapter addListener.onRailItemAddClicked());
+ }
+ }
+
+ @Override
+ void recycle() {
+ itemView.setOnClickListener(null);
+ }
+ }
+
public interface RailItemListener {
void onRailItemClicked(int distanceFromActive);
void onRailItemDeleteClicked(int distanceFromActive);
}
+
+ public interface RailItemAddListener {
+ void onRailItemAddClicked();
+ }
}
diff --git a/src/org/thoughtcrime/securesms/camera/Camera1Controller.java b/src/org/thoughtcrime/securesms/mediasend/Camera1Controller.java
similarity index 88%
rename from src/org/thoughtcrime/securesms/camera/Camera1Controller.java
rename to src/org/thoughtcrime/securesms/mediasend/Camera1Controller.java
index b680f0b033..ba6530e912 100644
--- a/src/org/thoughtcrime/securesms/camera/Camera1Controller.java
+++ b/src/org/thoughtcrime/securesms/mediasend/Camera1Controller.java
@@ -1,4 +1,4 @@
-package org.thoughtcrime.securesms.camera;
+package org.thoughtcrime.securesms.mediasend;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
@@ -11,21 +11,21 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public class Camera1Controller {
+class Camera1Controller {
private static final String TAG = Camera1Controller.class.getSimpleName();
- private final int screenWidth;
- private final int screenHeight;
+ private final int screenWidth;
+ private final int screenHeight;
+ private final OrderEnforcer enforcer;
+ private final EventListener eventListener;
private Camera camera;
private int cameraId;
- private OrderEnforcer enforcer;
- private EventListener eventListener;
private SurfaceTexture previewSurface;
private int screenRotation;
- public Camera1Controller(int preferredDirection, int screenWidth, int screenHeight, @NonNull EventListener eventListener) {
+ Camera1Controller(int preferredDirection, int screenWidth, int screenHeight, @NonNull EventListener eventListener) {
this.eventListener = eventListener;
this.enforcer = new OrderEnforcer<>(Stage.INITIALIZED, Stage.PREVIEW_STARTED);
this.cameraId = Camera.getNumberOfCameras() > 1 ? preferredDirection : Camera.CameraInfo.CAMERA_FACING_BACK;
@@ -33,10 +33,11 @@ public class Camera1Controller {
this.screenHeight = screenHeight;
}
- public void initialize() {
+ void initialize() {
Log.d(TAG, "initialize()");
if (Camera.getNumberOfCameras() <= 0) {
+ Log.w(TAG, "Device doesn't have any cameras.");
onCameraUnavailable();
return;
}
@@ -44,11 +45,13 @@ public class Camera1Controller {
try {
camera = Camera.open(cameraId);
} catch (Exception e) {
+ Log.w(TAG, "Failed to open camera.", e);
onCameraUnavailable();
return;
}
if (camera == null) {
+ Log.w(TAG, "Null camera instance.");
onCameraUnavailable();
return;
}
@@ -80,9 +83,9 @@ public class Camera1Controller {
eventListener.onPropertiesAvailable(getProperties());
}
- public void release() {
+ void release() {
Log.d(TAG, "release() called");
- enforcer.run(Stage.PREVIEW_STARTED, () -> {
+ enforcer.run(Stage.INITIALIZED, () -> {
Log.d(TAG, "release() executing");
previewSurface = null;
camera.stopPreview();
@@ -91,7 +94,7 @@ public class Camera1Controller {
});
}
- public void linkSurface(@NonNull SurfaceTexture surfaceTexture) {
+ void linkSurface(@NonNull SurfaceTexture surfaceTexture) {
Log.d(TAG, "linkSurface() called");
enforcer.run(Stage.INITIALIZED, () -> {
try {
@@ -108,7 +111,7 @@ public class Camera1Controller {
});
}
- public void capture(@NonNull CaptureCallback callback) {
+ void capture(@NonNull CaptureCallback callback) {
enforcer.run(Stage.PREVIEW_STARTED, () -> {
camera.takePicture(null, null, null, (data, camera) -> {
callback.onCaptureAvailable(data, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT);
@@ -116,7 +119,7 @@ public class Camera1Controller {
});
}
- public int flip() {
+ int flip() {
Log.d(TAG, "flip()");
SurfaceTexture surfaceTexture = previewSurface;
cameraId = (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK;
@@ -129,7 +132,7 @@ public class Camera1Controller {
return cameraId;
}
- public void setScreenRotation(int screenRotation) {
+ void setScreenRotation(int screenRotation) {
Log.d(TAG, "setScreenRotation(" + screenRotation + ") called");
enforcer.run(Stage.PREVIEW_STARTED, () -> {
Log.d(TAG, "setScreenRotation(" + screenRotation + ") executing");
@@ -221,7 +224,7 @@ public class Camera1Controller {
private final int previewWidth;
private final int previewHeight;
- public Properties(int cameraCount, int previewWidth, int previewHeight) {
+ Properties(int cameraCount, int previewWidth, int previewHeight) {
this.cameraCount = cameraCount;
this.previewWidth = previewWidth;
this.previewHeight = previewHeight;
@@ -231,11 +234,11 @@ public class Camera1Controller {
return cameraCount;
}
- public int getPreviewWidth() {
+ int getPreviewWidth() {
return previewWidth;
}
- public int getPreviewHeight() {
+ int getPreviewHeight() {
return previewHeight;
}
diff --git a/src/org/thoughtcrime/securesms/camera/Camera1Fragment.java b/src/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java
similarity index 91%
rename from src/org/thoughtcrime/securesms/camera/Camera1Fragment.java
rename to src/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java
index c7fdce0e78..652f6ea308 100644
--- a/src/org/thoughtcrime/securesms/camera/Camera1Fragment.java
+++ b/src/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java
@@ -1,6 +1,7 @@
-package org.thoughtcrime.securesms.camera;
+package org.thoughtcrime.securesms.mediasend;
import android.annotation.SuppressLint;
+import android.arch.lifecycle.ViewModelProviders;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Matrix;
@@ -21,8 +22,11 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.ImageButton;
@@ -55,6 +59,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
private Controller controller;
private OrderEnforcer orderEnforcer;
private Camera1Controller.Properties properties;
+ private MediaSendViewModel viewModel;
public static Camera1Fragment newInstance() {
return new Camera1Fragment();
@@ -76,6 +81,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
controller = (Controller) getActivity();
camera = new Camera1Controller(TextSecurePreferences.getDirectCaptureCameraId(getContext()), displaySize.x, displaySize.y, this);
orderEnforcer = new OrderEnforcer<>(Stage.SURFACE_AVAILABLE, Stage.CAMERA_PROPERTIES_AVAILABLE);
+ viewModel = ViewModelProviders.of(requireActivity(), new MediaSendViewModel.Factory(requireActivity().getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
}
@Nullable
@@ -103,11 +109,22 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
@Override
public void onResume() {
super.onResume();
+ viewModel.onCameraStarted();
camera.initialize();
+
+ if (cameraPreview.isAvailable()) {
+ orderEnforcer.markCompleted(Stage.SURFACE_AVAILABLE);
+ }
+
+ if (properties != null) {
+ orderEnforcer.markCompleted(Stage.CAMERA_PROPERTIES_AVAILABLE);
+ }
+
orderEnforcer.run(Stage.SURFACE_AVAILABLE, () -> {
camera.linkSurface(cameraPreview.getSurfaceTexture());
camera.setScreenRotation(controller.getDisplayRotation());
});
+
orderEnforcer.run(Stage.CAMERA_PROPERTIES_AVAILABLE, this::updatePreviewScale);
requireActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
@@ -118,6 +135,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
public void onPause() {
super.onPause();
camera.release();
+ orderEnforcer.reset();
}
@Override
@@ -128,6 +146,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ Log.d(TAG, "onSurfaceTextureAvailable");
orderEnforcer.markCompleted(Stage.SURFACE_AVAILABLE);
}
@@ -159,10 +178,6 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
controller.onCameraError();
}
- public void reset() {
- orderEnforcer.reset();
- }
-
@SuppressLint("ClickableViewAccessibility")
private void initControls() {
flipButton = getView().findViewById(R.id.camera_flip_button);
@@ -193,14 +208,14 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
orderEnforcer.run(Stage.CAMERA_PROPERTIES_AVAILABLE, () -> {
if (properties.getCameraCount() > 1) {
flipButton.setVisibility(properties.getCameraCount() > 1 ? View.VISIBLE : View.GONE);
- flipButton.setImageResource(TextSecurePreferences.getDirectCaptureCameraId(getContext()) == Camera.CameraInfo.CAMERA_FACING_BACK ? R.drawable.ic_camera_front
- : R.drawable.ic_camera_rear);
flipButton.setOnClickListener(v -> {
int newCameraId = camera.flip();
- flipButton.setImageResource(newCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? R.drawable.ic_camera_front
- : R.drawable.ic_camera_rear);
-
TextSecurePreferences.setDirectCaptureCameraId(getContext(), newCameraId);
+
+ Animation animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
+ animation.setDuration(200);
+ animation.setInterpolator(new DecelerateInterpolator());
+ flipButton.startAnimation(animation);
});
} else {
flipButton.setVisibility(View.GONE);
@@ -209,7 +224,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
}
private void onCaptureClicked() {
- reset();
+ orderEnforcer.reset();
Stopwatch fastCaptureTimer = new Stopwatch("Capture");
diff --git a/src/org/thoughtcrime/securesms/camera/FlipTransformation.java b/src/org/thoughtcrime/securesms/mediasend/FlipTransformation.java
similarity index 95%
rename from src/org/thoughtcrime/securesms/camera/FlipTransformation.java
rename to src/org/thoughtcrime/securesms/mediasend/FlipTransformation.java
index 3545b9fb85..d443dfefc6 100644
--- a/src/org/thoughtcrime/securesms/camera/FlipTransformation.java
+++ b/src/org/thoughtcrime/securesms/mediasend/FlipTransformation.java
@@ -1,4 +1,4 @@
-package org.thoughtcrime.securesms.camera;
+package org.thoughtcrime.securesms.mediasend;
import android.graphics.Bitmap;
import android.graphics.Canvas;
diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java
index 12e84eae0c..e6a90c6c16 100644
--- a/src/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java
+++ b/src/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java
@@ -93,6 +93,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo
public void onResume() {
super.onResume();
+ viewModel.onFolderPickerStarted();
requireActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java
index 0c40542a17..ffa3d5f615 100644
--- a/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java
+++ b/src/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java
@@ -4,33 +4,27 @@ import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
-import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.view.ActionMode;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp;
-import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -119,25 +113,27 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
public void onResume() {
super.onResume();
+ viewModel.onItemPickerStarted();
requireActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
- requireActivity().getMenuInflater().inflate(R.menu.mediapicker_default, menu);
-
- MenuItem beginSelectionButton = menu.findItem(R.id.mediapicker_menu_add);
-
- beginSelectionButton.setVisible(!viewModel.getCountButtonState().getValue().getVisibility());
+ if (viewModel.getCountButtonState().getValue() != null && viewModel.getCountButtonState().getValue().isVisible()) {
+ requireActivity().getMenuInflater().inflate(R.menu.mediapicker_multiselect, menu);
+ } else {
+ requireActivity().getMenuInflater().inflate(R.menu.mediapicker_default, menu);
+ }
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == R.id.mediapicker_menu_add) {
- adapter.setForcedMultiSelect(true);
- viewModel.onMultiSelectStarted();
- return true;
+ switch (item.getItemId()) {
+ case R.id.mediapicker_menu_add:
+ adapter.setForcedMultiSelect(true);
+ viewModel.onMultiSelectStarted();
+ return true;
}
return false;
}
@@ -162,7 +158,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
@Override
public void onMediaSelectionOverflow(int maxSelection) {
- Toast.makeText(requireContext(), getResources().getQuantityString(R.plurals.MediaPickerItemFragment_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
+ Toast.makeText(requireContext(), getResources().getQuantityString(R.plurals.MediaSendActivity_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
}
private void initToolbar(Toolbar toolbar) {
diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java
index 507dcda862..a5aa3d4a35 100644
--- a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java
+++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.mediasend;
+import android.Manifest;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
@@ -19,10 +20,10 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.TransportOption;
-import org.thoughtcrime.securesms.camera.Camera1Fragment;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MediaConstraints;
+import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.scribbles.ScribbleFragment;
@@ -58,8 +59,6 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
public static final String EXTRA_MESSAGE = "message";
public static final String EXTRA_TRANSPORT = "transport";
- private static final int MAX_PUSH = 32;
- private static final int MAX_SMS = 1;
private static final String KEY_ADDRESS = "address";
private static final String KEY_BODY = "body";
@@ -81,6 +80,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
private View countButton;
private TextView countButtonText;
+ private View cameraButton;
/**
* Get an intent to launch the media send flow starting with the picker.
@@ -134,14 +134,13 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
countButton = findViewById(R.id.mediasend_count_button);
countButtonText = findViewById(R.id.mediasend_count_button_text);
+ cameraButton = findViewById(R.id.mediasend_camera_button);
viewModel = ViewModelProviders.of(this, new MediaSendViewModel.Factory(getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
recipient = Recipient.from(this, Address.fromSerialized(getIntent().getStringExtra(KEY_ADDRESS)), true);
transport = getIntent().getParcelableExtra(KEY_TRANSPORT);
- viewModel.setMediaConstraints(transport.isSms() ? MediaConstraints.getMmsMediaConstraints(transport.getSimSubscriptionId().or(-1))
- : MediaConstraints.getPushMediaConstraints());
-
+ viewModel.setTransport(transport);
viewModel.onBodyChanged(getIntent().getStringExtra(KEY_BODY));
List media = getIntent().getParcelableArrayListExtra(KEY_MEDIA);
@@ -156,7 +155,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
} else if (!Util.isEmpty(media)) {
viewModel.onSelectedMediaChanged(this, media);
- Fragment fragment = MediaSendFragment.newInstance(transport, dynamicLanguage.getCurrentLocale());
+ Fragment fragment = MediaSendFragment.newInstance(recipient, transport, dynamicLanguage.getCurrentLocale());
getSupportFragmentManager().beginTransaction()
.replace(R.id.mediasend_fragment_container, fragment, TAG_SEND)
.commit();
@@ -168,6 +167,18 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
}
initializeCountButtonObserver(transport, dynamicLanguage.getCurrentLocale());
+ initializeCameraButtonObserver();
+ initializeErrorObserver();
+
+ cameraButton.setOnClickListener(v -> {
+ int maxSelection = viewModel.getMaxSelection();
+
+ if (viewModel.getSelectedMedia().getValue() != null && viewModel.getSelectedMedia().getValue().size() >= maxSelection) {
+ Toast.makeText(this, getResources().getQuantityString(R.plurals.MediaSendActivity_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
+ } else {
+ navigateToCamera();
+ }
+ });
}
@Override
@@ -189,11 +200,16 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
}
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
+ }
+
@Override
public void onFolderSelected(@NonNull MediaFolder folder) {
viewModel.onFolderSelected(folder.getBucketId());
- MediaPickerItemFragment fragment = MediaPickerItemFragment.newInstance(folder.getBucketId(), folder.getTitle(), transport.isSms() ? MAX_SMS :MAX_PUSH);
+ MediaPickerItemFragment fragment = MediaPickerItemFragment.newInstance(folder.getBucketId(), folder.getTitle(), viewModel.getMaxSelection());
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
.replace(R.id.mediasend_fragment_container, fragment, TAG_ITEM_PICKER)
@@ -203,14 +219,14 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
@Override
public void onMediaSelected(@NonNull String bucketId) {
- navigateToMediaSend(transport, dynamicLanguage.getCurrentLocale());
+ navigateToMediaSend(recipient, transport, dynamicLanguage.getCurrentLocale());
}
@Override
public void onAddMediaClicked(@NonNull String bucketId) {
// TODO: Get actual folder title somehow
MediaPickerFolderFragment folderFragment = MediaPickerFolderFragment.newInstance(recipient);
- MediaPickerItemFragment itemFragment = MediaPickerItemFragment.newInstance(bucketId, "", transport.isSms() ? MAX_SMS : MAX_PUSH);
+ MediaPickerItemFragment itemFragment = MediaPickerItemFragment.newInstance(bucketId, "", viewModel.getMaxSelection());
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.stationary, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
@@ -302,7 +318,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
Log.i(TAG, "Camera capture stored: " + media.getUri().toString());
viewModel.onImageCaptured(media);
- navigateToMediaSend(transport, dynamicLanguage.getCurrentLocale());
+ navigateToMediaSend(recipient, transport, dynamicLanguage.getCurrentLocale());
});
}
@@ -316,26 +332,42 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
if (buttonState == null) return;
countButtonText.setText(String.valueOf(buttonState.getCount()));
- countButton.setEnabled(buttonState.getVisibility());
- animateCountButtonVisibility(countButton, countButton.getVisibility(), buttonState.getVisibility() ? View.VISIBLE : View.GONE);
+ countButton.setEnabled(buttonState.isVisible());
+ animateButtonVisibility(countButton, countButton.getVisibility(), buttonState.isVisible() ? View.VISIBLE : View.GONE);
if (buttonState.getCount() > 0) {
- countButton.setOnClickListener(v -> {
- Camera1Fragment fragment = (Camera1Fragment) getSupportFragmentManager().findFragmentByTag(TAG_CAMERA);
- if (fragment != null) {
- fragment.reset();
- }
-
- navigateToMediaSend(transport, locale);
- });
+ countButton.setOnClickListener(v -> navigateToMediaSend(recipient, transport, locale));
} else {
countButton.setOnClickListener(null);
}
});
}
- private void navigateToMediaSend(@NonNull TransportOption transport, @NonNull Locale locale) {
- MediaSendFragment fragment = MediaSendFragment.newInstance(transport, locale);
+ private void initializeCameraButtonObserver() {
+ viewModel.getCameraButtonVisibility().observe(this, visible -> {
+ if (visible == null) return;
+ animateButtonVisibility(cameraButton, cameraButton.getVisibility(), visible ? View.VISIBLE : View.GONE);
+ });
+ }
+
+ private void initializeErrorObserver() {
+ viewModel.getError().observe(this, error -> {
+ if (error == null) return;
+
+ switch (error) {
+ case ITEM_TOO_LARGE:
+ Toast.makeText(this, R.string.MediaSendActivity_an_item_was_removed_because_it_exceeded_the_size_limit, Toast.LENGTH_LONG).show();
+ break;
+ case TOO_MANY_ITEMS:
+ int maxSelection = viewModel.getMaxSelection();
+ Toast.makeText(this, getResources().getQuantityString(R.plurals.MediaSendActivity_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
+ break;
+ }
+ });
+ }
+
+ private void navigateToMediaSend(@NonNull Recipient recipient, @NonNull TransportOption transport, @NonNull Locale locale) {
+ MediaSendFragment fragment = MediaSendFragment.newInstance(recipient, transport, locale);
String backstackTag = null;
if (getSupportFragmentManager().findFragmentByTag(TAG_SEND) != null) {
@@ -350,19 +382,44 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
.commit();
}
- private void animateCountButtonVisibility(View countButton, int oldVisibility, int newVisibility) {
+ private void navigateToCamera() {
+ Permissions.with(this)
+ .request(Manifest.permission.CAMERA)
+ .ifNecessary()
+ .withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_photo_camera_white_48dp)
+ .withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
+ .onAllGranted(() -> {
+ Camera1Fragment fragment = getOrCreateCameraFragment();
+ getSupportFragmentManager().beginTransaction()
+ .setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
+ .replace(R.id.mediasend_fragment_container, fragment, TAG_CAMERA)
+ .addToBackStack(null)
+ .commit();
+ })
+ .onAnyDenied(() -> Toast.makeText(MediaSendActivity.this, R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
+ .execute();
+ }
+
+ private Camera1Fragment getOrCreateCameraFragment() {
+ Camera1Fragment fragment = (Camera1Fragment) getSupportFragmentManager().findFragmentByTag(TAG_CAMERA);
+
+ return fragment != null ? fragment
+ : Camera1Fragment.newInstance();
+ }
+
+ private void animateButtonVisibility(View button, int oldVisibility, int newVisibility) {
if (oldVisibility == newVisibility) return;
- if (countButton.getAnimation() != null) {
- countButton.getAnimation().cancel();
- countButton.setVisibility(newVisibility);
+ if (button.getAnimation() != null) {
+ button.getAnimation().cancel();
+ button.setVisibility(newVisibility);
} else if (newVisibility == View.VISIBLE) {
- countButton.setVisibility(View.VISIBLE);
+ button.setVisibility(View.VISIBLE);
Animation animation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(250);
animation.setInterpolator(new OvershootInterpolator());
- countButton.startAnimation(animation);
+ button.startAnimation(animation);
} else {
Animation animation = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(150);
@@ -370,12 +427,11 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
animation.setAnimationListener(new SimpleAnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
- countButton.setVisibility(View.GONE);
+ button.setVisibility(View.GONE);
}
});
- countButton.startAnimation(animation);
+ button.startAnimation(animation);
}
-
}
}
diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java
index 6b5f24e536..7588dd92de 100644
--- a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java
+++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java
@@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.providers.BlobProvider;
+import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.scribbles.widget.ScribbleView;
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -51,6 +52,7 @@ import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.thoughtcrime.securesms.util.views.Stub;
+import org.whispersystems.libsignal.util.guava.Optional;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -72,12 +74,12 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
private static final String TAG = MediaSendFragment.class.getSimpleName();
+ private static final String KEY_ADDRESS = "address";
private static final String KEY_TRANSPORT = "transport";
private static final String KEY_LOCALE = "locale";
private InputAwareLayout hud;
private SendButton sendButton;
- private View addButton;
private ComposeText composeText;
private ViewGroup composeContainer;
private EmojiEditText captionText;
@@ -98,8 +100,9 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
private final Rect visibleBounds = new Rect();
- public static MediaSendFragment newInstance(@NonNull TransportOption transport, @NonNull Locale locale) {
+ public static MediaSendFragment newInstance(@NonNull Recipient recipient, @NonNull TransportOption transport, @NonNull Locale locale) {
Bundle args = new Bundle();
+ args.putParcelable(KEY_ADDRESS, recipient.getAddress());
args.putParcelable(KEY_TRANSPORT, transport);
args.putSerializable(KEY_LOCALE, locale);
@@ -145,7 +148,6 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
emojiDrawer = new Stub<>(view.findViewById(R.id.mediasend_emoji_drawer_stub));
fragmentPager = view.findViewById(R.id.mediasend_pager);
mediaRail = view.findViewById(R.id.mediasend_media_rail);
- addButton = view.findViewById(R.id.mediasend_add_button);
playbackControlsContainer = view.findViewById(R.id.mediasend_playback_controls_container);
charactersLeft = view.findViewById(R.id.mediasend_characters_left);
@@ -205,6 +207,11 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
composeText.append(viewModel.getBody());
+ Recipient recipient = Recipient.from(requireContext(), getArguments().getParcelable(KEY_ADDRESS), false);
+ String displayName = Optional.fromNullable(recipient.getName())
+ .or(Optional.fromNullable(recipient.getProfileName())
+ .or(recipient.getAddress().serialize()));
+ composeText.setHint(getString(R.string.MediaSendActivity_message_to_s, displayName), null);
if (TextSecurePreferences.isSystemEmojiPreferred(getContext())) {
emojiToggle.setVisibility(View.GONE);
@@ -264,12 +271,24 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
@Override
public void onKeyboardShown() {
- if (composeText.hasFocus()) {
+ if (sendButton.getSelectedTransport().isSms()) {
+ mediaRail.setVisibility(View.GONE);
composeContainer.setVisibility(View.VISIBLE);
captionText.setVisibility(View.GONE);
- } else if (captionText.hasFocus()) {
- mediaRail.setVisibility(View.GONE);
- composeContainer.setVisibility(View.GONE);
+ } else {
+ if (captionText.hasFocus()) {
+ mediaRail.setVisibility(View.VISIBLE);
+ composeContainer.setVisibility(View.GONE);
+ captionText.setVisibility(View.VISIBLE);
+ } else if (composeText.hasFocus()) {
+ mediaRail.setVisibility(View.VISIBLE);
+ composeContainer.setVisibility(View.VISIBLE);
+ captionText.setVisibility(View.GONE);
+ } else {
+ mediaRail.setVisibility(View.GONE);
+ composeContainer.setVisibility(View.VISIBLE);
+ captionText.setVisibility(View.GONE);
+ }
}
}
@@ -277,9 +296,15 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
public void onKeyboardHidden() {
composeContainer.setVisibility(View.VISIBLE);
- if (!Util.isEmpty(viewModel.getSelectedMedia().getValue()) && viewModel.getSelectedMedia().getValue().size() > 1) {
+ if (sendButton.getSelectedTransport().isSms()) {
+ mediaRail.setVisibility(View.GONE);
+ captionText.setVisibility(View.GONE);
+ } else {
mediaRail.setVisibility(View.VISIBLE);
- captionText.setVisibility(View.VISIBLE);
+
+ if (!Util.isEmpty(viewModel.getSelectedMedia().getValue()) && viewModel.getSelectedMedia().getValue().size() > 1) {
+ captionText.setVisibility(View.VISIBLE);
+ }
}
}
@@ -306,7 +331,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
fragmentPagerAdapter.setMedia(media);
- mediaRail.setVisibility(media.size() > 1 ? View.VISIBLE : View.GONE);
+ mediaRail.setVisibility(sendButton.getSelectedTransport().isSms() ? View.GONE : View.VISIBLE);
captionText.setVisibility((media.size() > 1 || media.get(0).getCaption().isPresent()) ? View.VISIBLE : View.GONE);
mediaRailAdapter.setMedia(media);
});
@@ -318,7 +343,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
mediaRailAdapter.setActivePosition(position);
mediaRail.smoothScrollToPosition(position);
- if (!fragmentPagerAdapter.getAllMedia().isEmpty()) {
+ if (fragmentPagerAdapter.getAllMedia().size() > position) {
captionText.setText(fragmentPagerAdapter.getAllMedia().get(position).getCaption().or(""));
}
@@ -337,18 +362,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
viewModel.getBucketId().observe(this, bucketId -> {
if (bucketId == null) return;
- if (sendButton.getSelectedTransport().isSms()) {
- addButton.setVisibility(View.GONE);
- } else {
- addButton.setVisibility(View.VISIBLE);
- addButton.setOnClickListener(v -> controller.onAddMediaClicked(bucketId));
- }
- });
-
- viewModel.getError().observe(this, error -> {
- if (error == MediaSendViewModel.Error.ITEM_TOO_LARGE) {
- Toast.makeText(requireContext(), R.string.MediaSendActivity_an_item_was_removed_because_it_exceeded_the_size_limit, Toast.LENGTH_LONG).show();
- }
+ mediaRailAdapter.setAddButtonListener(() -> controller.onAddMediaClicked(bucketId));
});
}
diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java
index b5c2417147..a4c674461d 100644
--- a/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java
+++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendViewModel.java
@@ -12,6 +12,7 @@ import android.text.TextUtils;
import com.annimon.stream.Stream;
+import org.thoughtcrime.securesms.TransportOption;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.util.MediaUtil;
@@ -30,6 +31,9 @@ import java.util.Map;
*/
class MediaSendViewModel extends ViewModel {
+ private static final int MAX_PUSH = 32;
+ private static final int MAX_SMS = 1;
+
private final Application application;
private final MediaRepository repository;
private final MutableLiveData> selectedMedia;
@@ -38,6 +42,7 @@ class MediaSendViewModel extends ViewModel {
private final MutableLiveData bucketId;
private final MutableLiveData> folders;
private final MutableLiveData countButtonState;
+ private final MutableLiveData cameraButtonVisibility;
private final SingleLiveEvent error;
private final Map savedDrawState;
@@ -46,27 +51,37 @@ class MediaSendViewModel extends ViewModel {
private CountButtonState.Visibility countButtonVisibility;
private boolean sentMedia;
private Optional lastImageCapture;
+ private int maxSelection;
private MediaSendViewModel(@NonNull Application application, @NonNull MediaRepository repository) {
- this.application = application;
- this.repository = repository;
- this.selectedMedia = new MutableLiveData<>();
- this.bucketMedia = new MutableLiveData<>();
- this.position = new MutableLiveData<>();
- this.bucketId = new MutableLiveData<>();
- this.folders = new MutableLiveData<>();
- this.countButtonState = new MutableLiveData<>();
- this.error = new SingleLiveEvent<>();
- this.savedDrawState = new HashMap<>();
- this.countButtonVisibility = CountButtonState.Visibility.CONDITIONAL;
- this.lastImageCapture = Optional.absent();
+ this.application = application;
+ this.repository = repository;
+ this.selectedMedia = new MutableLiveData<>();
+ this.bucketMedia = new MutableLiveData<>();
+ this.position = new MutableLiveData<>();
+ this.bucketId = new MutableLiveData<>();
+ this.folders = new MutableLiveData<>();
+ this.countButtonState = new MutableLiveData<>();
+ this.cameraButtonVisibility = new MutableLiveData<>();
+ this.error = new SingleLiveEvent<>();
+ this.savedDrawState = new HashMap<>();
+ this.countButtonVisibility = CountButtonState.Visibility.CONDITIONAL;
+ this.lastImageCapture = Optional.absent();
+ this.body = "";
position.setValue(-1);
countButtonState.setValue(new CountButtonState(0, CountButtonState.Visibility.CONDITIONAL));
+ cameraButtonVisibility.setValue(false);
}
- void setMediaConstraints(@NonNull MediaConstraints mediaConstraints) {
- this.mediaConstraints = mediaConstraints;
+ void setTransport(@NonNull TransportOption transport) {
+ if (transport.isSms()) {
+ maxSelection = MAX_SMS;
+ mediaConstraints = MediaConstraints.getMmsMediaConstraints(transport.getSimSubscriptionId().or(-1));
+ } else {
+ maxSelection = MAX_PUSH;
+ mediaConstraints = MediaConstraints.getPushMediaConstraints();
+ }
}
void onSelectedMediaChanged(@NonNull Context context, @NonNull List newMedia) {
@@ -75,13 +90,16 @@ class MediaSendViewModel extends ViewModel {
if (filteredMedia.size() != newMedia.size()) {
error.postValue(Error.ITEM_TOO_LARGE);
+ } else if (filteredMedia.size() > maxSelection) {
+ filteredMedia = filteredMedia.subList(0, maxSelection);
+ error.postValue(Error.TOO_MANY_ITEMS);
}
if (filteredMedia.size() > 0) {
String computedId = Stream.of(filteredMedia)
.skip(1)
- .reduce(filteredMedia.get(0).getBucketId().orNull(), (id, m) -> {
- if (Util.equals(id, m.getBucketId().orNull())) {
+ .reduce(filteredMedia.get(0).getBucketId().or(Media.ALL_MEDIA_BUCKET_ID), (id, m) -> {
+ if (Util.equals(id, m.getBucketId().or(Media.ALL_MEDIA_BUCKET_ID))) {
return id;
} else {
return Media.ALL_MEDIA_BUCKET_ID;
@@ -106,6 +124,7 @@ class MediaSendViewModel extends ViewModel {
void onImageEditorStarted() {
countButtonVisibility = CountButtonState.Visibility.FORCED_OFF;
countButtonState.setValue(new CountButtonState(getSelectedMediaOrDefault().size(), countButtonVisibility));
+ cameraButtonVisibility.setValue(false);
}
void onImageEditorEnded() {
@@ -113,6 +132,18 @@ class MediaSendViewModel extends ViewModel {
countButtonState.setValue(new CountButtonState(getSelectedMediaOrDefault().size(), countButtonVisibility));
}
+ void onCameraStarted() {
+ cameraButtonVisibility.setValue(false);
+ }
+
+ void onItemPickerStarted() {
+ cameraButtonVisibility.setValue(true);
+ }
+
+ void onFolderPickerStarted() {
+ cameraButtonVisibility.setValue(true);
+ }
+
void onBodyChanged(@NonNull CharSequence body) {
this.body = body;
}
@@ -143,6 +174,11 @@ class MediaSendViewModel extends ViewModel {
selected = new LinkedList<>();
}
+ if (selected.size() >= maxSelection) {
+ error.postValue(Error.TOO_MANY_ITEMS);
+ return;
+ }
+
lastImageCapture = Optional.of(media);
selected.add(media);
@@ -208,22 +244,30 @@ class MediaSendViewModel extends ViewModel {
return countButtonState;
}
- CharSequence getBody() {
+ @NonNull LiveData getCameraButtonVisibility() {
+ return cameraButtonVisibility;
+ }
+
+ @NonNull CharSequence getBody() {
return body;
}
- LiveData getPosition() {
+ @NonNull LiveData getPosition() {
return position;
}
- LiveData getBucketId() {
+ @NonNull LiveData getBucketId() {
return bucketId;
}
- LiveData getError() {
+ @NonNull LiveData getError() {
return error;
}
+ int getMaxSelection() {
+ return maxSelection;
+ }
+
private @NonNull List getSelectedMediaOrDefault() {
return selectedMedia.getValue() == null ? Collections.emptyList()
: selectedMedia.getValue();
@@ -252,7 +296,7 @@ class MediaSendViewModel extends ViewModel {
}
enum Error {
- ITEM_TOO_LARGE
+ ITEM_TOO_LARGE, TOO_MANY_ITEMS
}
static class CountButtonState {
@@ -268,7 +312,7 @@ class MediaSendViewModel extends ViewModel {
return count;
}
- boolean getVisibility() {
+ boolean isVisible() {
switch (visibility) {
case FORCED_ON: return true;
case FORCED_OFF: return false;
diff --git a/src/org/thoughtcrime/securesms/camera/OrderEnforcer.java b/src/org/thoughtcrime/securesms/mediasend/OrderEnforcer.java
similarity index 62%
rename from src/org/thoughtcrime/securesms/camera/OrderEnforcer.java
rename to src/org/thoughtcrime/securesms/mediasend/OrderEnforcer.java
index fd7cc2b9b1..6851dd97a4 100644
--- a/src/org/thoughtcrime/securesms/camera/OrderEnforcer.java
+++ b/src/org/thoughtcrime/securesms/mediasend/OrderEnforcer.java
@@ -1,11 +1,11 @@
-package org.thoughtcrime.securesms.camera;
+package org.thoughtcrime.securesms.mediasend;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Stack;
@SuppressWarnings("ConstantConditions")
public class OrderEnforcer {
@@ -22,21 +22,20 @@ public class OrderEnforcer {
if (isCompletedThrough(stage)) {
r.run();
} else {
- stages.get(stage).getActions().add(r);
+ stages.get(stage).addAction(r);
}
}
public synchronized void markCompleted(@NonNull E stage) {
- stages.get(stage).setCompleted(true);
+ stages.get(stage).markCompleted();
for (E s : stages.keySet()) {
StageDetails details = stages.get(s);
if (details.isCompleted()) {
- for (Runnable r : details.getActions()) {
- r.run();
+ while (details.hasAction()) {
+ details.popAction().run();
}
- details.getActions().clear();
} else {
break;
}
@@ -45,8 +44,7 @@ public class OrderEnforcer {
public synchronized void reset() {
for (StageDetails details : stages.values()) {
- details.setCompleted(false);
- details.getActions().clear();
+ details.reset();
}
}
@@ -62,19 +60,32 @@ public class OrderEnforcer {
}
private static class StageDetails {
- private boolean completed = false;
- private List actions = new CopyOnWriteArrayList<>();
+ private boolean completed = false;
+ private Stack actions = new Stack<>();
- @NonNull List getActions() {
- return actions;
+ boolean hasAction() {
+ return !actions.isEmpty();
+ }
+
+ @Nullable Runnable popAction() {
+ return actions.pop();
+ }
+
+ void addAction(@NonNull Runnable runnable) {
+ actions.push(runnable);
+ }
+
+ void reset() {
+ actions.clear();
+ completed = false;
}
boolean isCompleted() {
return completed;
}
- void setCompleted(boolean completed) {
- this.completed = completed;
+ void markCompleted() {
+ completed = true;
}
}
}
diff --git a/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java b/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java
index e16d33b063..cd8c0fdeb3 100644
--- a/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java
+++ b/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java
@@ -41,11 +41,10 @@ import java.util.Set;
public class ScribbleHud extends InputAwareLayout implements ViewTreeObserver.OnGlobalLayoutListener {
private View drawButton;
- private View highlightButton;
private View textButton;
- private View stickerButton;
private View undoButton;
private View deleteButton;
+ private View confirmButton;
private View saveButton;
private VerticalSlideColorPicker colorPicker;
private RecyclerView colorPalette;
@@ -111,11 +110,10 @@ public class ScribbleHud extends InputAwareLayout implements ViewTreeObserver.On
setOrientation(VERTICAL);
drawButton = findViewById(R.id.scribble_draw_button);
- highlightButton = findViewById(R.id.scribble_highlight_button);
textButton = findViewById(R.id.scribble_text_button);
- stickerButton = findViewById(R.id.scribble_sticker_button);
undoButton = findViewById(R.id.scribble_undo_button);
deleteButton = findViewById(R.id.scribble_delete_button);
+ confirmButton = findViewById(R.id.scribble_confirm_button);
saveButton = findViewById(R.id.scribble_save_button);
colorPicker = findViewById(R.id.scribble_color_picker);
colorPalette = findViewById(R.id.scribble_color_palette);
@@ -163,6 +161,8 @@ public class ScribbleHud extends InputAwareLayout implements ViewTreeObserver.On
setMode(Mode.NONE);
});
+ confirmButton.setOnClickListener(v -> setMode(Mode.NONE));
+
sendButton.addOnTransportChangedListener((newTransport, manuallySelected) -> {
presentCharactersRemaining();
composeText.setTransport(newTransport);
@@ -255,84 +255,70 @@ public class ScribbleHud extends InputAwareLayout implements ViewTreeObserver.On
private void presentModeNone() {
drawButton.setVisibility(VISIBLE);
- highlightButton.setVisibility(VISIBLE);
textButton.setVisibility(VISIBLE);
- stickerButton.setVisibility(VISIBLE);
undoButton.setVisibility(GONE);
deleteButton.setVisibility(GONE);
+ confirmButton.setVisibility(GONE);
colorPicker.setVisibility(GONE);
colorPalette.setVisibility(GONE);
drawButton.setOnClickListener(v -> setMode(Mode.DRAW));
- highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT));
textButton.setOnClickListener(v -> setMode(Mode.TEXT));
- stickerButton.setOnClickListener(v -> setMode(Mode.STICKER));
}
private void presentModeDraw() {
- drawButton.setVisibility(VISIBLE);
+ confirmButton.setVisibility(VISIBLE);
undoButton.setVisibility(VISIBLE);
colorPicker.setVisibility(VISIBLE);
colorPalette.setVisibility(VISIBLE);
- highlightButton.setVisibility(GONE);
+ drawButton.setVisibility(GONE);
textButton.setVisibility(GONE);
- stickerButton.setVisibility(GONE);
deleteButton.setVisibility(GONE);
- drawButton.setOnClickListener(v -> setMode(Mode.NONE));
colorPicker.setOnColorChangeListener(standardOnColorChangeListener);
colorPicker.setActiveColor(Color.RED);
}
private void presentModeHighlight() {
- highlightButton.setVisibility(VISIBLE);
+ confirmButton.setVisibility(VISIBLE);
undoButton.setVisibility(VISIBLE);
colorPicker.setVisibility(VISIBLE);
colorPalette.setVisibility(VISIBLE);
drawButton.setVisibility(GONE);
textButton.setVisibility(GONE);
- stickerButton.setVisibility(GONE);
deleteButton.setVisibility(GONE);
- highlightButton.setOnClickListener(v -> setMode(Mode.NONE));
-
colorPicker.setOnColorChangeListener(highlightOnColorChangeListener);
colorPicker.setActiveColor(Color.YELLOW);
}
private void presentModeText() {
- textButton.setVisibility(VISIBLE);
+ confirmButton.setVisibility(VISIBLE);
deleteButton.setVisibility(VISIBLE);
colorPicker.setVisibility(VISIBLE);
colorPalette.setVisibility(VISIBLE);
+ textButton.setVisibility(GONE);
drawButton.setVisibility(GONE);
- highlightButton.setVisibility(GONE);
- stickerButton.setVisibility(GONE);
undoButton.setVisibility(GONE);
- textButton.setOnClickListener(v -> setMode(Mode.NONE));
-
colorPicker.setOnColorChangeListener(standardOnColorChangeListener);
colorPicker.setActiveColor(Color.WHITE);
}
private void presentModeSticker() {
- stickerButton.setVisibility(VISIBLE);
deleteButton.setVisibility(VISIBLE);
+ confirmButton.setVisibility(VISIBLE);
drawButton.setVisibility(GONE);
- highlightButton.setVisibility(GONE);
textButton.setVisibility(GONE);
undoButton.setVisibility(GONE);
colorPicker.setVisibility(GONE);
colorPalette.setVisibility(GONE);
-
- stickerButton.setOnClickListener(v -> setMode(Mode.NONE));
}
private void presentCharactersRemaining() {
diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java b/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java
index 3c4fe80968..e33dbd00b6 100644
--- a/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java
+++ b/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java
@@ -136,6 +136,7 @@ public class MotionView extends FrameLayout implements TextWatcher {
this.addView(editText);
this.editText.clearFocus();
this.editText.addTextChangedListener(this);
+ this.editText.setId(R.id.motion_view_edittext);
// init listeners
this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener());
diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java b/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java
index 497a830b1c..27071eae7b 100644
--- a/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java
+++ b/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java
@@ -43,7 +43,7 @@ import org.thoughtcrime.securesms.R;
public class VerticalSlideColorPicker extends View {
- private static final float INDICATOR_TO_BAR_WIDTH_RATIO = 0.8f;
+ private static final float INDICATOR_TO_BAR_WIDTH_RATIO = 0.5f;
private Paint paint;
private Paint strokePaint;
@@ -131,9 +131,9 @@ public class VerticalSlideColorPicker extends View {
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- path.addCircle(centerX, borderWidth + colorPickerRadius, colorPickerRadius, Path.Direction.CW);
+ path.addCircle(centerX, borderWidth + colorPickerRadius + indicatorRadius, colorPickerRadius, Path.Direction.CW);
path.addRect(colorPickerBody, Path.Direction.CW);
- path.addCircle(centerX, viewHeight - (borderWidth + colorPickerRadius), colorPickerRadius, Path.Direction.CW);
+ path.addCircle(centerX, viewHeight - (borderWidth + colorPickerRadius + indicatorRadius), colorPickerRadius, Path.Direction.CW);
bitmapCanvas.drawColor(Color.TRANSPARENT);
@@ -178,7 +178,10 @@ public class VerticalSlideColorPicker extends View {
indicatorRadius = (viewWidth / 2) - borderWidth;
colorPickerRadius = (barWidth / 2) - borderWidth;
- colorPickerBody = new RectF(centerX - colorPickerRadius, borderWidth + colorPickerRadius, centerX + colorPickerRadius, viewHeight - (borderWidth + colorPickerRadius));
+ colorPickerBody = new RectF(centerX - colorPickerRadius,
+ borderWidth + colorPickerRadius + indicatorRadius,
+ centerX + colorPickerRadius,
+ viewHeight - (borderWidth + colorPickerRadius + indicatorRadius));
LinearGradient gradient = new LinearGradient(0, colorPickerBody.top, 0, colorPickerBody.bottom, colors, null, Shader.TileMode.CLAMP);
paint.setShader(gradient);
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/camera/OrderEnforcerTest.java b/test/unitTest/java/org/thoughtcrime/securesms/camera/OrderEnforcerTest.java
index bef016c92f..fece0f7805 100644
--- a/test/unitTest/java/org/thoughtcrime/securesms/camera/OrderEnforcerTest.java
+++ b/test/unitTest/java/org/thoughtcrime/securesms/camera/OrderEnforcerTest.java
@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.camera;
import org.junit.Test;
+import org.thoughtcrime.securesms.mediasend.OrderEnforcer;
import java.util.concurrent.atomic.AtomicInteger;