diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index a403a3ff3..896c0ba8b 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 340FC8D0205BF2FA007AEB0F /* OWSBackupIO.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC8CE205BF2FA007AEB0F /* OWSBackupIO.m */; }; 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */; }; 34277A5E20751BDC006049F2 /* OWSQuotedMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34277A5C20751BDC006049F2 /* OWSQuotedMessageView.m */; }; + 3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */; }; 3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3430FE171F7751D4000EC51B /* GiphyAPI.swift */; }; 34330A5A1E7875FB00DF2FB9 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */; }; 34330A5C1E787A9800DF2FB9 /* dripicons-v2.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5B1E787A9800DF2FB9 /* dripicons-v2.ttf */; }; @@ -641,6 +642,8 @@ 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUIMisc.m; sourceTree = ""; }; 34277A5C20751BDC006049F2 /* OWSQuotedMessageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQuotedMessageView.m; sourceTree = ""; }; 34277A5D20751BDC006049F2 /* OWSQuotedMessageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQuotedMessageView.h; sourceTree = ""; }; + 3427C64120F500DE00EEC730 /* OWSMessageTimerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageTimerView.h; sourceTree = ""; }; + 3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageTimerView.m; sourceTree = ""; }; 3430FE171F7751D4000EC51B /* GiphyAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiphyAPI.swift; sourceTree = ""; }; 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "fontawesome-webfont.ttf"; sourceTree = ""; }; 34330A5B1E787A9800DF2FB9 /* dripicons-v2.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dripicons-v2.ttf"; sourceTree = ""; }; @@ -1771,6 +1774,8 @@ 34D920E620E179C200D51158 /* OWSMessageFooterView.m */, 34DBF000206BD5A400025978 /* OWSMessageTextView.h */, 34DBEFFF206BD5A400025978 /* OWSMessageTextView.m */, + 3427C64120F500DE00EEC730 /* OWSMessageTimerView.h */, + 3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */, 34277A5D20751BDC006049F2 /* OWSQuotedMessageView.h */, 34277A5C20751BDC006049F2 /* OWSQuotedMessageView.m */, 34D1F0A51F867BFC0066283D /* OWSSystemMessageCell.h */, @@ -3363,6 +3368,7 @@ 45A663C51F92EC760027B59E /* GroupTableViewCell.swift in Sources */, 34CA631B2097806F00E526A0 /* OWSContactShareView.m in Sources */, 34D1F0861F8678AA0066283D /* ConversationViewController.m in Sources */, + 3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */, B90418E6183E9DD40038554A /* DateUtil.m in Sources */, 340FC8BD204DAC8D007AEB0F /* ShowGroupMembersViewController.m in Sources */, 459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */, diff --git a/Signal/Images.xcassets/disappearing_message_00.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_00.imageset/Contents.json new file mode 100644 index 000000000..c028a06a6 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_00.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer00_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer00_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer00_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@1x.png b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@1x.png new file mode 100644 index 000000000..8a4ec9164 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@2x.png b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@2x.png new file mode 100644 index 000000000..34e3d6969 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@3x.png b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@3x.png new file mode 100644 index 000000000..74e7720d8 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_00.imageset/timer00_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_05.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_05.imageset/Contents.json new file mode 100644 index 000000000..63a927fe6 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_05.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer05_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer05_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer05_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@1x.png b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@1x.png new file mode 100644 index 000000000..524f4d518 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@2x.png b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@2x.png new file mode 100644 index 000000000..f54c4d939 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@3x.png b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@3x.png new file mode 100644 index 000000000..11aa27a72 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_05.imageset/timer05_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_10.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_10.imageset/Contents.json new file mode 100644 index 000000000..4cc3baa74 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_10.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer10_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer10_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer10_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@1x.png b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@1x.png new file mode 100644 index 000000000..eb50d7115 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@2x.png b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@2x.png new file mode 100644 index 000000000..2ef4e25c0 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@3x.png b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@3x.png new file mode 100644 index 000000000..201ae3a93 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_10.imageset/timer10_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_15.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_15.imageset/Contents.json new file mode 100644 index 000000000..fe7ff22dc --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_15.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer15_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer15_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer15_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@1x.png b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@1x.png new file mode 100644 index 000000000..7db85f05e Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@2x.png b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@2x.png new file mode 100644 index 000000000..303b2fb71 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@3x.png b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@3x.png new file mode 100644 index 000000000..82f1230cf Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_15.imageset/timer15_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_20.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_20.imageset/Contents.json new file mode 100644 index 000000000..7e7a3b970 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_20.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer20_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer20_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer20_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@1x.png b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@1x.png new file mode 100644 index 000000000..bc0855db7 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@2x.png b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@2x.png new file mode 100644 index 000000000..4a5d97c64 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@3x.png b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@3x.png new file mode 100644 index 000000000..67329f1be Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_20.imageset/timer20_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_25.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_25.imageset/Contents.json new file mode 100644 index 000000000..2b621a91c --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_25.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer25_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer25_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer25_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@1x.png b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@1x.png new file mode 100644 index 000000000..7868a6e02 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@2x.png b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@2x.png new file mode 100644 index 000000000..012a2d27a Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@3x.png b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@3x.png new file mode 100644 index 000000000..4175c2990 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_25.imageset/timer25_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_30.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_30.imageset/Contents.json new file mode 100644 index 000000000..4538c3702 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_30.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer30_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer30_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer30_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@1x.png b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@1x.png new file mode 100644 index 000000000..1449809eb Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@2x.png b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@2x.png new file mode 100644 index 000000000..f17acc8ca Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@3x.png b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@3x.png new file mode 100644 index 000000000..74c247f93 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_30.imageset/timer30_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_35.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_35.imageset/Contents.json new file mode 100644 index 000000000..9ee54129b --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_35.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer35_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer35_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer35_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@1x.png b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@1x.png new file mode 100644 index 000000000..b58558208 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@2x.png b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@2x.png new file mode 100644 index 000000000..6382a8b85 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@3x.png b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@3x.png new file mode 100644 index 000000000..7af8e393b Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_35.imageset/timer35_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_40.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_40.imageset/Contents.json new file mode 100644 index 000000000..7826d3b5f --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_40.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer40_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer40_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer40_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@1x.png b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@1x.png new file mode 100644 index 000000000..4e49b5c3a Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@2x.png b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@2x.png new file mode 100644 index 000000000..c7576f226 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@3x.png b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@3x.png new file mode 100644 index 000000000..d596ab639 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_40.imageset/timer40_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_45.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_45.imageset/Contents.json new file mode 100644 index 000000000..193fd62d4 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_45.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer45_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer45_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer45_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@1x.png b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@1x.png new file mode 100644 index 000000000..d14d8b9f8 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@2x.png b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@2x.png new file mode 100644 index 000000000..d0c963ac8 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@3x.png b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@3x.png new file mode 100644 index 000000000..84e667d10 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_45.imageset/timer45_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_50.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_50.imageset/Contents.json new file mode 100644 index 000000000..bfbb47f13 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_50.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer50_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer50_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer50_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@1x.png b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@1x.png new file mode 100644 index 000000000..73b8c3aa4 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@2x.png b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@2x.png new file mode 100644 index 000000000..b881cd0c8 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@3x.png b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@3x.png new file mode 100644 index 000000000..fff2f9b6c Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_50.imageset/timer50_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_55.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_55.imageset/Contents.json new file mode 100644 index 000000000..ecbe7ee70 --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_55.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer55_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer55_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer55_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@1x.png b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@1x.png new file mode 100644 index 000000000..dd189a540 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@2x.png b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@2x.png new file mode 100644 index 000000000..635a7e467 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@3x.png b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@3x.png new file mode 100644 index 000000000..0c26dfe75 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_55.imageset/timer55_12@3x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_60.imageset/Contents.json b/Signal/Images.xcassets/disappearing_message_60.imageset/Contents.json new file mode 100644 index 000000000..96fc1606d --- /dev/null +++ b/Signal/Images.xcassets/disappearing_message_60.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timer60_12@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "timer60_12@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "timer60_12@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@1x.png b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@1x.png new file mode 100644 index 000000000..910d08785 Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@1x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@2x.png b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@2x.png new file mode 100644 index 000000000..e0a14ac7f Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@2x.png differ diff --git a/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@3x.png b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@3x.png new file mode 100644 index 000000000..099455efb Binary files /dev/null and b/Signal/Images.xcassets/disappearing_message_60.imageset/timer60_12@3x.png differ diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m index 12593870c..04884c67c 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageFooterView.m @@ -4,6 +4,7 @@ #import "OWSMessageFooterView.h" #import "DateUtil.h" +#import "OWSMessageTimerView.h" #import "Signal-Swift.h" #import @@ -13,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) UILabel *timestampLabel; @property (nonatomic) UIImageView *statusIndicatorImageView; +@property (nonatomic) OWSMessageTimerView *messageTimerView; @end @@ -38,9 +40,20 @@ NS_ASSUME_NONNULL_BEGIN self.axis = UILayoutConstraintAxisHorizontal; self.spacing = self.hSpacing; self.alignment = UIStackViewAlignmentCenter; + self.distribution = UIStackViewDistributionEqualSpacing; + + UIStackView *leftStackView = [UIStackView new]; + leftStackView.axis = UILayoutConstraintAxisHorizontal; + leftStackView.spacing = self.hSpacing; + leftStackView.alignment = UIStackViewAlignmentCenter; + [self addArrangedSubview:leftStackView]; self.timestampLabel = [UILabel new]; - [self addArrangedSubview:self.timestampLabel]; + [leftStackView addArrangedSubview:self.timestampLabel]; + + self.messageTimerView = [OWSMessageTimerView new]; + [self.messageTimerView setContentHuggingHigh]; + [leftStackView addArrangedSubview:self.messageTimerView]; self.statusIndicatorImageView = [UIImageView new]; [self.statusIndicatorImageView setContentHuggingHigh]; @@ -90,6 +103,18 @@ NS_ASSUME_NONNULL_BEGIN } self.timestampLabel.textColor = textColor; + if (viewItem.isExpiringMessage) { + TSMessage *message = (TSMessage *)viewItem.interaction; + uint64_t expirationTimestamp = message.expiresAt; + uint32_t expiresInSeconds = message.expiresInSeconds; + [self.messageTimerView configureWithExpirationTimestamp:expirationTimestamp + initialDurationSeconds:expiresInSeconds + tintColor:textColor]; + self.messageTimerView.hidden = NO; + } else { + self.messageTimerView.hidden = YES; + } + if (viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) { TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction; @@ -218,6 +243,11 @@ NS_ASSUME_NONNULL_BEGIN result.width += (self.maxImageWidth + self.hSpacing); } } + + if (viewItem.isExpiringMessage) { + result.width += ([OWSMessageTimerView measureSize].width + self.hSpacing); + } + return CGSizeCeil(result); } @@ -236,6 +266,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)prepareForReuse { [self.statusIndicatorImageView.layer removeAllAnimations]; + + [self.messageTimerView prepareForReuse]; } @end diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h new file mode 100644 index 000000000..0fad8f9f0 --- /dev/null +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSMessageTimerView : UIView + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; + +- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp + initialDurationSeconds:(uint32_t)initialDurationSeconds + tintColor:(UIColor *)tintColor; + +- (void)prepareForReuse; + ++ (CGSize)measureSize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m new file mode 100644 index 000000000..ed7096193 --- /dev/null +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageTimerView.m @@ -0,0 +1,195 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSMessageTimerView.h" +#import "ConversationViewController.h" +#import "NSDate+OWS.h" +#import "OWSMath.h" +#import "UIColor+OWS.h" +#import "UIView+OWS.h" +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +const CGFloat kDisappearingMessageIconSize = 12.f; + +@interface OWSMessageTimerView () + +@property (nonatomic) uint32_t initialDurationSeconds; +@property (nonatomic) uint64_t expirationTimestamp; +@property (nonatomic) UIColor *tintColor; + +@property (nonatomic) UIImageView *imageView; + +@property (nonatomic, nullable) NSTimer *animationTimer; + +// 0 == about to expire, 12 == just started countdown. +@property (nonatomic) NSInteger progress12; + + +@end + +#pragma mark - + +@implementation OWSMessageTimerView + +- (void)dealloc +{ + [self clearAnimation]; +} + +- (instancetype)init +{ + self = [super initWithFrame:CGRectZero]; + if (!self) { + return self; + } + + [self commonInit]; + + return self; +} + +- (void)commonInit +{ + self.imageView = [UIImageView new]; + [self addSubview:self.imageView]; + [self.imageView autoPinToSuperviewEdges]; + [self.imageView autoSetDimension:ALDimensionWidth toSize:kDisappearingMessageIconSize]; + [self.imageView autoSetDimension:ALDimensionHeight toSize:kDisappearingMessageIconSize]; +} + +- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp + initialDurationSeconds:(uint32_t)initialDurationSeconds + tintColor:(UIColor *)tintColor; +{ + self.expirationTimestamp = expirationTimestamp; + self.initialDurationSeconds = initialDurationSeconds; + self.tintColor = tintColor; + + [self updateProgress12]; + [self updateIcon]; + [self startAnimation]; +} + +- (void)updateProgress12 +{ + BOOL hasStartedCountdown = self.expirationTimestamp > 0; + if (!hasStartedCountdown) { + self.progress12 = 12; + return; + } + + CGFloat secondsLeft = MAX(0, (self.expirationTimestamp - [NSDate ows_millisecondTimeStamp]) / 1000.f); + CGFloat progress = 0.f; + if (self.initialDurationSeconds > 0) { + progress = CGFloatClamp(secondsLeft / self.initialDurationSeconds, 0.f, 1.f); + } + OWSAssert(progress >= 0.f); + OWSAssert(progress <= 1.f); + + self.progress12 = (NSInteger)round(CGFloatClamp(progress, 0.f, 1.f) * 12); +} + +- (void)setProgress12:(NSInteger)progress12 +{ + if (_progress12 == progress12) { + return; + } + _progress12 = progress12; + + [self updateIcon]; +} + +- (void)updateIcon +{ + self.imageView.image = [[self progressIcon] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + self.imageView.tintColor = self.tintColor; +} + +- (UIImage *)progressIcon +{ + OWSAssert(self.progress12 >= 0); + OWSAssert(self.progress12 <= 12); + + UIImage *_Nullable image; + switch (self.progress12) { + default: + case 0: + image = [UIImage imageNamed:@"disappearing_message_00"]; + break; + case 1: + image = [UIImage imageNamed:@"disappearing_message_05"]; + break; + case 2: + image = [UIImage imageNamed:@"disappearing_message_10"]; + break; + case 3: + image = [UIImage imageNamed:@"disappearing_message_15"]; + break; + case 4: + image = [UIImage imageNamed:@"disappearing_message_20"]; + break; + case 5: + image = [UIImage imageNamed:@"disappearing_message_25"]; + break; + case 6: + image = [UIImage imageNamed:@"disappearing_message_30"]; + break; + case 7: + image = [UIImage imageNamed:@"disappearing_message_35"]; + break; + case 8: + image = [UIImage imageNamed:@"disappearing_message_40"]; + break; + case 9: + image = [UIImage imageNamed:@"disappearing_message_45"]; + break; + case 10: + image = [UIImage imageNamed:@"disappearing_message_50"]; + break; + case 11: + image = [UIImage imageNamed:@"disappearing_message_55"]; + break; + case 12: + image = [UIImage imageNamed:@"disappearing_message_60"]; + break; + } + OWSAssert(image); + OWSAssert(image.size.width == kDisappearingMessageIconSize); + OWSAssert(image.size.height == kDisappearingMessageIconSize); + return image; +} + +- (void)startAnimation +{ + [self clearAnimation]; + + self.animationTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.1f + target:self + selector:@selector(updateProgress12) + userInfo:nil + repeats:YES]; +} + +- (void)clearAnimation +{ + [self.animationTimer invalidate]; + self.animationTimer = nil; +} + +- (void)prepareForReuse +{ + [self clearAnimation]; +} + ++ (CGSize)measureSize +{ + return CGSizeMake(kDisappearingMessageIconSize, kDisappearingMessageIconSize); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index a61cfb319..ef8e6b0fd 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -4807,6 +4807,7 @@ typedef enum : NSUInteger { TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction; MessageReceiptStatus receiptStatus = [MessageRecipientStatusUtils recipientStatusWithOutgoingMessage:outgoingMessage]; + BOOL isDisappearingMessage = outgoingMessage.isExpiringMessage; if (nextViewItem && nextViewItem.interaction.interactionType == interactionType) { TSOutgoingMessage *nextOutgoingMessage = (TSOutgoingMessage *)nextViewItem.interaction; @@ -4816,10 +4817,12 @@ typedef enum : NSUInteger { // We can skip the "outgoing message status" footer if the next message // has the same footer and no "date break" separates us... - // ...but always show "failed to send" status. - shouldHideFooter = ([timestampText isEqualToString:nextTimestampText] - && receiptStatus == nextReceiptStatus - && outgoingMessage.messageState != TSOutgoingMessageStateFailed && !nextViewItem.shouldShowDate); + // ...but always show "failed to send" status + // ...and always show the "disappearing messages" animation. + shouldHideFooter + = ([timestampText isEqualToString:nextTimestampText] && receiptStatus == nextReceiptStatus + && outgoingMessage.messageState != TSOutgoingMessageStateFailed && !nextViewItem.shouldShowDate + && !isDisappearingMessage); } // clustering @@ -4843,6 +4846,7 @@ typedef enum : NSUInteger { TSIncomingMessage *incomingMessage = (TSIncomingMessage *)viewItem.interaction; NSString *incomingSenderId = incomingMessage.authorId; OWSAssert(incomingSenderId.length > 0); + BOOL isDisappearingMessage = incomingMessage.isExpiringMessage; NSString *_Nullable nextIncomingSenderId = nil; if (nextViewItem && nextViewItem.interaction.interactionType == interactionType) { @@ -4855,8 +4859,10 @@ typedef enum : NSUInteger { NSString *nextTimestampText = [DateUtil formatTimestampShort:nextViewItem.interaction.timestamp]; // We can skip the "incoming message status" footer in a cluster if the next message // has the same footer and no "date break" separates us. - shouldHideFooter = [timestampText isEqualToString:nextTimestampText] && !nextViewItem.shouldShowDate && - [NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId]; + // ...but always show the "disappearing messages" animation. + shouldHideFooter = ([timestampText isEqualToString:nextTimestampText] && !nextViewItem.shouldShowDate && + [NSObject isNullableObject:nextIncomingSenderId equalTo:incomingSenderId] + && !isDisappearingMessage); } // clustering diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h index b6cb4cd64..cb0c4aa69 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.h @@ -54,6 +54,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType); @property (nonatomic, readonly) BOOL hasQuotedAttachment; @property (nonatomic, readonly) BOOL hasQuotedText; +@property (nonatomic, readonly) BOOL isExpiringMessage; + @property (nonatomic) BOOL shouldShowDate; @property (nonatomic) BOOL shouldShowSenderAvatar; @property (nonatomic, nullable) NSAttributedString *senderName; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index 42bb737a5..e84e4ce5f 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -138,6 +138,17 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return self.hasQuotedAttachment || self.hasQuotedText; } +- (BOOL)isExpiringMessage +{ + if (self.interaction.interactionType != OWSInteractionType_OutgoingMessage + && self.interaction.interactionType != OWSInteractionType_IncomingMessage) { + return NO; + } + + TSMessage *message = (TSMessage *)self.interaction; + return message.isExpiringMessage; +} + - (void)setShouldShowDate:(BOOL)shouldShowDate { if (_shouldShowDate == shouldShowDate) { diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.h b/SignalServiceKit/src/Messages/Interactions/TSMessage.h index 4c672c7e2..c0e7219ce 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.h @@ -45,7 +45,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)setQuotedMessageThumbnailAttachmentStream:(TSAttachmentStream *)attachmentStream; -- (BOOL)shouldStartExpireTimer; - (BOOL)shouldStartExpireTimerWithTransaction:(YapDatabaseReadTransaction *)transaction; #pragma mark - Update With... Methods diff --git a/SignalServiceKit/src/Messages/Interactions/TSMessage.m b/SignalServiceKit/src/Messages/Interactions/TSMessage.m index a14972967..5e9c0ccf1 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSMessage.m @@ -182,15 +182,6 @@ static const NSUInteger OWSMessageSchemaVersion = 4; [self updateExpiresAt]; } -- (BOOL)shouldStartExpireTimer -{ - __block BOOL result; - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { - result = [self shouldStartExpireTimerWithTransaction:transaction]; - }]; - return result; -} - - (BOOL)shouldStartExpireTimerWithTransaction:(YapDatabaseReadTransaction *)transaction { return self.isExpiringMessage;