Skip to content

Instantly share code, notes, and snippets.

@KlavierCat
Created March 10, 2021 22:06
Show Gist options
  • Save KlavierCat/0b1e3214f8d9ca1b0f4e523b38a3df88 to your computer and use it in GitHub Desktop.
Save KlavierCat/0b1e3214f8d9ca1b0f4e523b38a3df88 to your computer and use it in GitHub Desktop.
sample jscpd JSON report
{
"statistics": {
"detectionDate": "2021-03-07T12:36:50.737Z",
"formats": {
"swift": {
"sources": {
"ViewControllers/ConversationView/CV/CVComponents/CVComponentViewOnce.swift": {
"lines": 364,
"tokens": 2530,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentUnreadIndicator.swift": {
"lines": 201,
"tokens": 1480,
"sources": 1,
"clones": 4,
"duplicatedLines": 82,
"duplicatedTokens": 599,
"percentage": 40.8,
"percentageTokens": 40.47,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentTypingIndicator.swift": {
"lines": 197,
"tokens": 1518,
"sources": 1,
"clones": 1,
"duplicatedLines": 25,
"duplicatedTokens": 180,
"percentage": 12.69,
"percentageTokens": 11.86,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentThreadDetails.swift": {
"lines": 432,
"tokens": 3628,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentSystemMessage.swift": {
"lines": 919,
"tokens": 7386,
"sources": 1,
"clones": 1,
"duplicatedLines": 20,
"duplicatedTokens": 146,
"percentage": 2.18,
"percentageTokens": 1.98,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentSticker.swift": {
"lines": 196,
"tokens": 1490,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentSenderName.swift": {
"lines": 115,
"tokens": 868,
"sources": 1,
"clones": 1,
"duplicatedLines": 13,
"duplicatedTokens": 110,
"percentage": 11.3,
"percentageTokens": 12.67,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentReactions.swift": {
"lines": 77,
"tokens": 515,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentQuotedReply.swift": {
"lines": 88,
"tokens": 585,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentLinkPreview.swift": {
"lines": 76,
"tokens": 490,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentGenericAttachment.swift": {
"lines": 330,
"tokens": 2786,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentFooter.swift": {
"lines": 371,
"tokens": 2994,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentDateHeader.swift": {
"lines": 209,
"tokens": 1526,
"sources": 1,
"clones": 2,
"duplicatedLines": 37,
"duplicatedTokens": 273,
"percentage": 17.7,
"percentageTokens": 17.89,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentContactShare.swift": {
"lines": 92,
"tokens": 629,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentBottomButtons.swift": {
"lines": 144,
"tokens": 1073,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentBodyText.swift": {
"lines": 648,
"tokens": 4993,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentBodyMedia.swift": {
"lines": 434,
"tokens": 3435,
"sources": 1,
"clones": 1,
"duplicatedLines": 13,
"duplicatedTokens": 110,
"percentage": 3,
"percentageTokens": 3.2,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponents/CVComponentAudioAttachment.swift": {
"lines": 203,
"tokens": 1485,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Individual/CallKit/CallKitCallUIAdaptee.swift": {
"lines": 470,
"tokens": 3200,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Individual/CallKit/CallKitCallManager.swift": {
"lines": 147,
"tokens": 1130,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/SecondaryLinking/SecondaryLinkingSetDeviceNameViewController.swift": {
"lines": 162,
"tokens": 1240,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/SecondaryLinking/SecondaryLinkingQRCodeViewController.swift": {
"lines": 130,
"tokens": 1009,
"sources": 1,
"clones": 1,
"duplicatedLines": 7,
"duplicatedTokens": 81,
"percentage": 5.38,
"percentageTokens": 8.03,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/SecondaryLinking/SecondaryLinkingPrepViewController.swift": {
"lines": 115,
"tokens": 890,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/SecondaryLinking/ProvisioningController.swift": {
"lines": 247,
"tokens": 2062,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/Device Transfer/OnboardingTransferQRCodeViewController.swift": {
"lines": 184,
"tokens": 1204,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/Device Transfer/OnboardingTransferProgressViewController.swift": {
"lines": 145,
"tokens": 971,
"sources": 1,
"clones": 2,
"duplicatedLines": 35,
"duplicatedTokens": 239,
"percentage": 24.14,
"percentageTokens": 24.61,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/Device Transfer/OnboardingTransferChoiceViewController.swift": {
"lines": 239,
"tokens": 1936,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/Transitions/MediaZoomAnimationController.swift": {
"lines": 159,
"tokens": 1262,
"sources": 1,
"clones": 3,
"duplicatedLines": 48,
"duplicatedTokens": 391,
"percentage": 30.19,
"percentageTokens": 30.98,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/Transitions/MediaPresentationContext.swift": {
"lines": 68,
"tokens": 449,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/Transitions/MediaInteractiveDismiss.swift": {
"lines": 125,
"tokens": 857,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/Transitions/MediaDismissAnimationController.swift": {
"lines": 255,
"tokens": 2086,
"sources": 1,
"clones": 3,
"duplicatedLines": 48,
"duplicatedTokens": 391,
"percentage": 18.82,
"percentageTokens": 18.74,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift": {
"lines": 648,
"tokens": 5183,
"sources": 1,
"clones": 19,
"duplicatedLines": 410,
"duplicatedTokens": 3534,
"percentage": 63.27,
"percentageTokens": 68.18,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Reactions Details/EmojiReactorsTableView.swift": {
"lines": 124,
"tokens": 1034,
"sources": 1,
"clones": 2,
"duplicatedLines": 23,
"duplicatedTokens": 223,
"percentage": 18.55,
"percentageTokens": 21.57,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Reactions Details/EmojiCountsCollectionView.swift": {
"lines": 150,
"tokens": 1176,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Emoji Picker/EmojiSkinTonePicker.swift": {
"lines": 304,
"tokens": 3141,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift": {
"lines": 355,
"tokens": 2947,
"sources": 1,
"clones": 13,
"duplicatedLines": 239,
"duplicatedTokens": 2139,
"percentage": 67.32,
"percentageTokens": 72.58,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Emoji Picker/EmojiPickerSectionToolbar.swift": {
"lines": 125,
"tokens": 1035,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Emoji Picker/EmojiPickerCollectionView.swift": {
"lines": 343,
"tokens": 2956,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/ReusableMediaView.swift": {
"lines": 511,
"tokens": 3271,
"sources": 1,
"clones": 8,
"duplicatedLines": 204,
"duplicatedTokens": 1260,
"percentage": 39.92,
"percentageTokens": 38.52,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/QuotedMessageView.swift": {
"lines": 608,
"tokens": 4911,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/LoadMoreMessagesView.swift": {
"lines": 38,
"tokens": 240,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVReactionCountsView.swift": {
"lines": 260,
"tokens": 2313,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVMediaView.swift": {
"lines": 278,
"tokens": 2099,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVMediaCache.swift": {
"lines": 124,
"tokens": 914,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVMediaAlbumView.swift": {
"lines": 437,
"tokens": 3650,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVContactShareView.swift": {
"lines": 110,
"tokens": 1051,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/CVAttachmentProgressView.swift": {
"lines": 526,
"tokens": 3940,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/AudioWaveformProgressView.swift": {
"lines": 199,
"tokens": 1531,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/Cells/AudioMessageView.swift": {
"lines": 331,
"tokens": 2869,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/OWSStackView.swift": {
"lines": 75,
"tokens": 511,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVViewStateSnapshot.swift": {
"lines": 63,
"tokens": 402,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVUpdate.swift": {
"lines": 315,
"tokens": 2549,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVStackView.swift": {
"lines": 63,
"tokens": 481,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVRenderState.swift": {
"lines": 107,
"tokens": 744,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVRenderItem.swift": {
"lines": 162,
"tokens": 1233,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVNode.swift": {
"lines": 95,
"tokens": 629,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVMessageMapping.swift": {
"lines": 579,
"tokens": 4727,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVLoader.swift": {
"lines": 365,
"tokens": 2934,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVLoadRequest.swift": {
"lines": 244,
"tokens": 1561,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVLoadCoordinator.swift": {
"lines": 859,
"tokens": 5507,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVLoadContext.swift": {
"lines": 88,
"tokens": 582,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVItemViewState.swift": {
"lines": 647,
"tokens": 5027,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVItemViewModelImpl.swift": {
"lines": 233,
"tokens": 1446,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVItemModel.swift": {
"lines": 44,
"tokens": 263,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponentState+GroupLink.swift": {
"lines": 169,
"tokens": 1455,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponentDelegate.swift": {
"lines": 239,
"tokens": 1530,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVComponent.swift": {
"lines": 378,
"tokens": 2436,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVCell.swift": {
"lines": 379,
"tokens": 2621,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVAvatarBuilder.swift": {
"lines": 71,
"tokens": 560,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVAudioPlayback.swift": {
"lines": 277,
"tokens": 1609,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CV/CVAttachments.swift": {
"lines": 66,
"tokens": 470,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Profile/UsernameViewController.swift": {
"lines": 295,
"tokens": 2037,
"sources": 1,
"clones": 3,
"duplicatedLines": 64,
"duplicatedTokens": 397,
"percentage": 21.69,
"percentageTokens": 19.49,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Profile/ProfileSettingsViewController.swift": {
"lines": 354,
"tokens": 2869,
"sources": 1,
"clones": 4,
"duplicatedLines": 68,
"duplicatedTokens": 589,
"percentage": 19.21,
"percentageTokens": 20.53,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Profile/ProfileNameViewController.swift": {
"lines": 254,
"tokens": 1687,
"sources": 1,
"clones": 3,
"duplicatedLines": 63,
"duplicatedTokens": 387,
"percentage": 24.8,
"percentageTokens": 22.94,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Profile/ProfileBioViewController.swift": {
"lines": 366,
"tokens": 2783,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Privacy/PrivacySettingsViewController.swift": {
"lines": 242,
"tokens": 1759,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Privacy/AdvancedPrivacySettingsViewController.swift": {
"lines": 258,
"tokens": 1757,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Notifications/NotificationSettingsViewController.swift": {
"lines": 150,
"tokens": 1190,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Notifications/NotificationSettingsSoundViewController.swift": {
"lines": 162,
"tokens": 1130,
"sources": 1,
"clones": 1,
"duplicatedLines": 19,
"duplicatedTokens": 121,
"percentage": 11.73,
"percentageTokens": 10.71,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/Notifications/NotificationSettingsContentViewController.swift": {
"lines": 39,
"tokens": 289,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Individual/NonCallKitCallUIAdaptee.swift": {
"lines": 188,
"tokens": 1210,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Individual/CallUIAdapter.swift": {
"lines": 327,
"tokens": 2469,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallViewController.swift": {
"lines": 797,
"tokens": 6510,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallVideoOverflow.swift": {
"lines": 189,
"tokens": 1490,
"sources": 1,
"clones": 2,
"duplicatedLines": 54,
"duplicatedTokens": 336,
"percentage": 28.57,
"percentageTokens": 22.55,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallVideoGridLayout.swift": {
"lines": 153,
"tokens": 1426,
"sources": 1,
"clones": 2,
"duplicatedLines": 48,
"duplicatedTokens": 313,
"percentage": 31.37,
"percentageTokens": 21.95,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallVideoGrid.swift": {
"lines": 192,
"tokens": 1496,
"sources": 1,
"clones": 2,
"duplicatedLines": 54,
"duplicatedTokens": 336,
"percentage": 28.13,
"percentageTokens": 22.46,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallTooltip.swift": {
"lines": 27,
"tokens": 239,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallSpeakerToastView.swift": {
"lines": 45,
"tokens": 351,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallNotificationView.swift": {
"lines": 269,
"tokens": 2216,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallMemberView.swift": {
"lines": 460,
"tokens": 3785,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallMemberSheet.swift": {
"lines": 628,
"tokens": 5351,
"sources": 1,
"clones": 12,
"duplicatedLines": 270,
"duplicatedTokens": 2361,
"percentage": 42.99,
"percentageTokens": 44.12,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/Group/GroupCallErrorView.swift": {
"lines": 141,
"tokens": 1144,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Emoji/EmojiWithSkinTones.swift": {
"lines": 55,
"tokens": 614,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Emoji/Emoji+Available.swift": {
"lines": 118,
"tokens": 1030,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/SelfSignedIdentity.swift": {
"lines": 241,
"tokens": 1986,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService.swift": {
"lines": 456,
"tokens": 3362,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService+URL.swift": {
"lines": 77,
"tokens": 757,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService+State.swift": {
"lines": 84,
"tokens": 626,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService+Restore.swift": {
"lines": 251,
"tokens": 1871,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService+MultipeerDelegates.swift": {
"lines": 343,
"tokens": 2832,
"sources": 1,
"clones": 2,
"duplicatedLines": 50,
"duplicatedTokens": 424,
"percentage": 14.58,
"percentageTokens": 14.97,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferService+Manifest.swift": {
"lines": 265,
"tokens": 2229,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Device Transfer/DeviceTransferOperation.swift": {
"lines": 139,
"tokens": 1305,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Backup/OWSBackupLazyRestore.swift": {
"lines": 171,
"tokens": 1255,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Backup/OWSBackupAPI.swift": {
"lines": 734,
"tokens": 6173,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Wallpapers/WallpaperSettingsViewController.swift": {
"lines": 380,
"tokens": 3163,
"sources": 1,
"clones": 1,
"duplicatedLines": 16,
"duplicatedTokens": 116,
"percentage": 4.21,
"percentageTokens": 3.67,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Wallpapers/SetWallpaperViewController.swift": {
"lines": 238,
"tokens": 2018,
"sources": 1,
"clones": 1,
"duplicatedLines": 16,
"duplicatedTokens": 116,
"percentage": 6.72,
"percentageTokens": 5.75,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Wallpapers/PreviewWallpaperViewController.swift": {
"lines": 507,
"tokens": 4397,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Utils/MessageRecipientStatusUtils.swift": {
"lines": 162,
"tokens": 1398,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/ReplaceAdminViewController.swift": {
"lines": 76,
"tokens": 475,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/OWSAddToContactViewController.swift": {
"lines": 133,
"tokens": 1035,
"sources": 1,
"clones": 1,
"duplicatedLines": 8,
"duplicatedTokens": 75,
"percentage": 6.02,
"percentageTokens": 7.25,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/NameCollisionResolutionViewController.swift": {
"lines": 320,
"tokens": 2987,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/MemberActionSheet.swift": {
"lines": 364,
"tokens": 3018,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupViewHelper.swift": {
"lines": 173,
"tokens": 1090,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift": {
"lines": 181,
"tokens": 1652,
"sources": 1,
"clones": 6,
"duplicatedLines": 72,
"duplicatedTokens": 816,
"percentage": 39.78,
"percentageTokens": 49.39,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupMemberRequestsAndInvitesViewController.swift": {
"lines": 594,
"tokens": 5055,
"sources": 1,
"clones": 2,
"duplicatedLines": 26,
"duplicatedTokens": 328,
"percentage": 4.38,
"percentageTokens": 6.49,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupLinkViewController.swift": {
"lines": 412,
"tokens": 3287,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupLinkQRCodeViewController.swift": {
"lines": 92,
"tokens": 704,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupAttributesViewController.swift": {
"lines": 316,
"tokens": 2380,
"sources": 1,
"clones": 3,
"duplicatedLines": 68,
"duplicatedTokens": 523,
"percentage": 21.52,
"percentageTokens": 21.97,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/GroupAttributesEditorHelper.swift": {
"lines": 257,
"tokens": 1898,
"sources": 1,
"clones": 2,
"duplicatedLines": 28,
"duplicatedTokens": 295,
"percentage": 10.89,
"percentageTokens": 15.54,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/ConversationSettingsViewController+LegacyGroups.swift": {
"lines": 251,
"tokens": 1925,
"sources": 1,
"clones": 2,
"duplicatedLines": 30,
"duplicatedTokens": 223,
"percentage": 11.95,
"percentageTokens": 11.58,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/ConversationSettingsViewController+Header.swift": {
"lines": 300,
"tokens": 2612,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift": {
"lines": 825,
"tokens": 7127,
"sources": 1,
"clones": 8,
"duplicatedLines": 88,
"duplicatedTokens": 828,
"percentage": 10.67,
"percentageTokens": 11.62,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/AddToGroupViewController.swift": {
"lines": 279,
"tokens": 2380,
"sources": 1,
"clones": 1,
"duplicatedLines": 18,
"duplicatedTokens": 138,
"percentage": 6.45,
"percentageTokens": 5.8,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ThreadSettings/AddGroupMembersViewController.swift": {
"lines": 274,
"tokens": 1969,
"sources": 1,
"clones": 2,
"duplicatedLines": 50,
"duplicatedTokens": 385,
"percentage": 18.25,
"percentageTokens": 19.55,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Stickers/StickerPackViewController.swift": {
"lines": 539,
"tokens": 4227,
"sources": 1,
"clones": 2,
"duplicatedLines": 24,
"duplicatedTokens": 213,
"percentage": 4.45,
"percentageTokens": 5.04,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Stickers/ManageStickersViewController.swift": {
"lines": 596,
"tokens": 4927,
"sources": 1,
"clones": 1,
"duplicatedLines": 9,
"duplicatedTokens": 97,
"percentage": 1.51,
"percentageTokens": 1.97,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/RegistrationController.swift": {
"lines": 76,
"tokens": 276,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingVerificationViewController.swift": {
"lines": 706,
"tokens": 5762,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingSplashViewController.swift": {
"lines": 108,
"tokens": 889,
"sources": 1,
"clones": 1,
"duplicatedLines": 7,
"duplicatedTokens": 81,
"percentage": 6.48,
"percentageTokens": 9.11,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingProfileCreationViewController.swift": {
"lines": 470,
"tokens": 3920,
"sources": 1,
"clones": 2,
"duplicatedLines": 49,
"duplicatedTokens": 311,
"percentage": 10.43,
"percentageTokens": 7.93,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingPinAttemptsExhaustedViewController.swift": {
"lines": 105,
"tokens": 768,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingPhoneNumberViewController.swift": {
"lines": 672,
"tokens": 5494,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingPhoneNumberDiscoverabilityViewController.swift": {
"lines": 213,
"tokens": 1673,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingPermissionsViewController.swift": {
"lines": 113,
"tokens": 841,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingModeSwitchConfirmationViewController.swift": {
"lines": 93,
"tokens": 702,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingCaptchaViewController.swift": {
"lines": 206,
"tokens": 1672,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/OnboardingBaseViewController.swift": {
"lines": 162,
"tokens": 1308,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/Onboarding2FAViewController.swift": {
"lines": 487,
"tokens": 3650,
"sources": 1,
"clones": 4,
"duplicatedLines": 39,
"duplicatedTokens": 355,
"percentage": 8.01,
"percentageTokens": 9.73,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Registration/BackupRestoreViewController.swift": {
"lines": 164,
"tokens": 1147,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/RecipientPicker/RecipientPickerDelegate.swift": {
"lines": 225,
"tokens": 1760,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/RecipientPicker/ComposeViewController.swift": {
"lines": 144,
"tokens": 1132,
"sources": 1,
"clones": 4,
"duplicatedLines": 59,
"duplicatedTokens": 456,
"percentage": 40.97,
"percentageTokens": 40.28,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/RecipientPicker/AddToBlockListViewController.swift": {
"lines": 133,
"tokens": 985,
"sources": 1,
"clones": 4,
"duplicatedLines": 59,
"duplicatedTokens": 456,
"percentage": 44.36,
"percentageTokens": 46.29,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/SendMediaNavigationController.swift": {
"lines": 888,
"tokens": 7319,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/SendMediaBottomButton.swift": {
"lines": 84,
"tokens": 625,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/PhotoLibrary.swift": {
"lines": 382,
"tokens": 3294,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/PhotoCollectionPickerController.swift": {
"lines": 132,
"tokens": 1032,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/PhotoCaptureDismiss.swift": {
"lines": 109,
"tokens": 818,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/ImagePickerController.swift": {
"lines": 656,
"tokens": 5007,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Photos/AvatarViewController.swift": {
"lines": 133,
"tokens": 1162,
"sources": 1,
"clones": 2,
"duplicatedLines": 22,
"duplicatedTokens": 170,
"percentage": 16.54,
"percentageTokens": 14.63,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/NewGroupView/NewGroupState.swift": {
"lines": 19,
"tokens": 118,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/NewGroupView/NewGroupMembersViewController.swift": {
"lines": 124,
"tokens": 785,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/NewGroupView/NewGroupMembersBar.swift": {
"lines": 428,
"tokens": 3394,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/NewGroupView/NewGroupConfirmViewController.swift": {
"lines": 557,
"tokens": 4346,
"sources": 1,
"clones": 3,
"duplicatedLines": 46,
"duplicatedTokens": 349,
"percentage": 8.26,
"percentageTokens": 8.03,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/NewGroupView/BaseGroupMemberViewController.swift": {
"lines": 626,
"tokens": 4782,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/MediaTileViewController.swift": {
"lines": 848,
"tokens": 6884,
"sources": 1,
"clones": 4,
"duplicatedLines": 48,
"duplicatedTokens": 374,
"percentage": 5.66,
"percentageTokens": 5.43,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MediaGallery/MediaPageViewController.swift": {
"lines": 930,
"tokens": 7323,
"sources": 1,
"clones": 2,
"duplicatedLines": 25,
"duplicatedTokens": 222,
"percentage": 2.69,
"percentageTokens": 3.03,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/HomeView/ConversationSplitViewController.swift": {
"lines": 632,
"tokens": 4585,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/HomeView/ConversationSearchViewController.swift": {
"lines": 497,
"tokens": 3605,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GifPicker/GifPickerViewController.swift": {
"lines": 663,
"tokens": 5245,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GifPicker/GifPickerLayout.swift": {
"lines": 138,
"tokens": 1179,
"sources": 1,
"clones": 2,
"duplicatedLines": 48,
"duplicatedTokens": 313,
"percentage": 34.78,
"percentageTokens": 26.55,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GifPicker/GifPickerCell.swift": {
"lines": 280,
"tokens": 1990,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Device Transfer/DeviceTransferQRScanningViewController.swift": {
"lines": 236,
"tokens": 1864,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Device Transfer/DeviceTransferProgressViewController.swift": {
"lines": 107,
"tokens": 718,
"sources": 1,
"clones": 1,
"duplicatedLines": 22,
"duplicatedTokens": 137,
"percentage": 20.56,
"percentageTokens": 19.08,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Device Transfer/DeviceTransferNavigationController.swift": {
"lines": 130,
"tokens": 1042,
"sources": 1,
"clones": 4,
"duplicatedLines": 50,
"duplicatedTokens": 432,
"percentage": 38.46,
"percentageTokens": 41.46,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Device Transfer/DeviceTransferInitialViewController.swift": {
"lines": 58,
"tokens": 448,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/LogViewController.swift": {
"lines": 145,
"tokens": 1154,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUIStress.swift": {
"lines": 355,
"tokens": 3221,
"sources": 1,
"clones": 2,
"duplicatedLines": 30,
"duplicatedTokens": 266,
"percentage": 8.45,
"percentageTokens": 8.26,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUIProfile.swift": {
"lines": 74,
"tokens": 578,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUINotifications.swift": {
"lines": 233,
"tokens": 1914,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUIMessages+OWS.swift": {
"lines": 76,
"tokens": 648,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUIFileBrowser.swift": {
"lines": 371,
"tokens": 3438,
"sources": 1,
"clones": 4,
"duplicatedLines": 38,
"duplicatedTokens": 460,
"percentage": 10.24,
"percentageTokens": 13.38,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUIDataStoreViewController.swift": {
"lines": 100,
"tokens": 849,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugUICalling.swift": {
"lines": 74,
"tokens": 611,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/DebugUI/DebugContactsUtils.swift": {
"lines": 38,
"tokens": 303,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/UnreadIndicatorInteraction.swift": {
"lines": 45,
"tokens": 308,
"sources": 1,
"clones": 3,
"duplicatedLines": 48,
"duplicatedTokens": 357,
"percentage": 106.67,
"percentageTokens": 115.91,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/TypingIndicatorInteraction.swift": {
"lines": 48,
"tokens": 332,
"sources": 1,
"clones": 1,
"duplicatedLines": 15,
"duplicatedTokens": 105,
"percentage": 31.25,
"percentageTokens": 31.63,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ThreadDetailsInteraction.swift": {
"lines": 44,
"tokens": 295,
"sources": 1,
"clones": 1,
"duplicatedLines": 15,
"duplicatedTokens": 117,
"percentage": 34.09,
"percentageTokens": 39.66,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/MessageSelectionView.swift": {
"lines": 58,
"tokens": 428,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/MessageRequestView.swift": {
"lines": 378,
"tokens": 2859,
"sources": 1,
"clones": 4,
"duplicatedLines": 56,
"duplicatedTokens": 594,
"percentage": 14.81,
"percentageTokens": 20.78,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/MemberRequestView.swift": {
"lines": 131,
"tokens": 974,
"sources": 1,
"clones": 1,
"duplicatedLines": 33,
"duplicatedTokens": 236,
"percentage": 25.19,
"percentageTokens": 24.23,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/InteractionReactionState.swift": {
"lines": 57,
"tokens": 518,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/DateHeaderInteraction.swift": {
"lines": 44,
"tokens": 295,
"sources": 1,
"clones": 1,
"duplicatedLines": 18,
"duplicatedTokens": 135,
"percentage": 40.91,
"percentageTokens": 45.76,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewLayout.swift": {
"lines": 461,
"tokens": 3350,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+Wallpaper.swift": {
"lines": 46,
"tokens": 319,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+Selection.swift": {
"lines": 391,
"tokens": 3166,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+Scroll.swift": {
"lines": 802,
"tokens": 5822,
"sources": 1,
"clones": 2,
"duplicatedLines": 22,
"duplicatedTokens": 196,
"percentage": 2.74,
"percentageTokens": 3.37,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+OWS.swift": {
"lines": 500,
"tokens": 3430,
"sources": 1,
"clones": 1,
"duplicatedLines": 48,
"duplicatedTokens": 318,
"percentage": 9.6,
"percentageTokens": 9.27,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+MessageRequest.swift": {
"lines": 320,
"tokens": 2552,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+MessageActionsDelegate.swift": {
"lines": 110,
"tokens": 797,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+Mentions.swift": {
"lines": 32,
"tokens": 292,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+LastVisibleSortId.swift": {
"lines": 178,
"tokens": 1375,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+GestureRecognizers.swift": {
"lines": 345,
"tokens": 2483,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+CVC.swift": {
"lines": 742,
"tokens": 4674,
"sources": 1,
"clones": 2,
"duplicatedLines": 36,
"duplicatedTokens": 194,
"percentage": 4.85,
"percentageTokens": 4.15,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+BottomBar.swift": {
"lines": 349,
"tokens": 2040,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationViewController+Banners.swift": {
"lines": 534,
"tokens": 4813,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationInputTextView.swift": {
"lines": 235,
"tokens": 1739,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/ConversationHeaderView.swift": {
"lines": 158,
"tokens": 1162,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/CVViewState.swift": {
"lines": 571,
"tokens": 3821,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ConversationView/BlockingGroupMigrationView.swift": {
"lines": 122,
"tokens": 921,
"sources": 1,
"clones": 1,
"duplicatedLines": 33,
"duplicatedTokens": 236,
"percentage": 27.05,
"percentageTokens": 25.62,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Attachment Keyboard/RecentPhotoCollectionView.swift": {
"lines": 352,
"tokens": 2906,
"sources": 1,
"clones": 2,
"duplicatedLines": 27,
"duplicatedTokens": 211,
"percentage": 7.67,
"percentageTokens": 7.26,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Attachment Keyboard/AttachmentKeyboard.swift": {
"lines": 317,
"tokens": 2278,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/Attachment Keyboard/AttachmentFormatPickerView.swift": {
"lines": 204,
"tokens": 1572,
"sources": 1,
"clones": 1,
"duplicatedLines": 15,
"duplicatedTokens": 109,
"percentage": 7.35,
"percentageTokens": 6.93,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/ThemeSettingsTableViewController.swift": {
"lines": 70,
"tokens": 516,
"sources": 1,
"clones": 2,
"duplicatedLines": 23,
"duplicatedTokens": 192,
"percentage": 32.86,
"percentageTokens": 37.21,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/TestingViewController.swift": {
"lines": 200,
"tokens": 1593,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/PhoneNumberSharingSettingsTableViewController.swift": {
"lines": 86,
"tokens": 599,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/PhoneNumberDiscoverabilitySettingsTableViewController.swift": {
"lines": 82,
"tokens": 576,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/NetworkInterfacePreferenceViewController.swift": {
"lines": 57,
"tokens": 474,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/MediaDownloadSettingsViewController.swift": {
"lines": 82,
"tokens": 618,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/LinkedDevicesTableViewController.swift": {
"lines": 374,
"tokens": 2584,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/InternalSettingsViewController.swift": {
"lines": 155,
"tokens": 1455,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/HelpViewController.swift": {
"lines": 110,
"tokens": 979,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/FlagsViewController.swift": {
"lines": 36,
"tokens": 317,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/DataSettingsTableViewController.swift": {
"lines": 136,
"tokens": 1031,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/ContactSupportViewController.swift": {
"lines": 319,
"tokens": 2609,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/ComposeSupportEmailOperation.swift": {
"lines": 243,
"tokens": 1871,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/ChatsSettingsViewController.swift": {
"lines": 140,
"tokens": 1019,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/AppearanceSettingsTableViewController.swift": {
"lines": 82,
"tokens": 649,
"sources": 1,
"clones": 2,
"duplicatedLines": 23,
"duplicatedTokens": 192,
"percentage": 28.05,
"percentageTokens": 29.58,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/AppSettingsViewController.swift": {
"lines": 268,
"tokens": 2507,
"sources": 1,
"clones": 1,
"duplicatedLines": 9,
"duplicatedTokens": 94,
"percentage": 3.36,
"percentageTokens": 3.75,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/AdvancedPinSettingsTableViewController.swift": {
"lines": 49,
"tokens": 431,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AppSettings/AccountSettingsViewController.swift": {
"lines": 329,
"tokens": 2564,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/SharingSuggestionsMegaphone.swift": {
"lines": 37,
"tokens": 294,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/ResearchMegaphone.swift": {
"lines": 153,
"tokens": 1233,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/PinReminderMegaphone.swift": {
"lines": 49,
"tokens": 407,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/NotificationPermissionReminderMegaphone.swift": {
"lines": 210,
"tokens": 1730,
"sources": 1,
"clones": 4,
"duplicatedLines": 51,
"duplicatedTokens": 454,
"percentage": 24.29,
"percentageTokens": 26.24,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/LinkPreviewsMegaphone.swift": {
"lines": 37,
"tokens": 300,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/IntroducingPINs.swift": {
"lines": 241,
"tokens": 2109,
"sources": 1,
"clones": 1,
"duplicatedLines": 14,
"duplicatedTokens": 107,
"percentage": 5.81,
"percentageTokens": 5.07,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/GroupsV2AndMentionsSplash.swift": {
"lines": 170,
"tokens": 1456,
"sources": 1,
"clones": 2,
"duplicatedLines": 30,
"duplicatedTokens": 233,
"percentage": 17.65,
"percentageTokens": 16,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/GroupCallsMegaphone.swift": {
"lines": 20,
"tokens": 138,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/Upgrade Views/ContactPermissionReminderMegaphone.swift": {
"lines": 71,
"tokens": 508,
"sources": 1,
"clones": 1,
"duplicatedLines": 14,
"duplicatedTokens": 124,
"percentage": 19.72,
"percentageTokens": 24.41,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/LocalVideoView.swift": {
"lines": 112,
"tokens": 727,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/CallHeader.swift": {
"lines": 320,
"tokens": 2670,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/CallControls.swift": {
"lines": 286,
"tokens": 2441,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/UserInterface/CallButton.swift": {
"lines": 145,
"tokens": 1361,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Signaling/WebRTCCallMessageHandler.swift": {
"lines": 171,
"tokens": 1215,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Signaling/TurnServerInfo.swift": {
"lines": 27,
"tokens": 194,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Individual/OutboundIndividualCallInitiator.swift": {
"lines": 96,
"tokens": 596,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Individual/IndividualCall.swift": {
"lines": 221,
"tokens": 1438,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Group/GroupCallUpdateMessageHandler.swift": {
"lines": 80,
"tokens": 763,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/Group/GroupCallRemoteVideoManager.swift": {
"lines": 172,
"tokens": 1572,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/VoiceNoteLock.swift": {
"lines": 75,
"tokens": 657,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/TypingIndicatorView.swift": {
"lines": 209,
"tokens": 1689,
"sources": 1,
"clones": 1,
"duplicatedLines": 10,
"duplicatedTokens": 79,
"percentage": 4.78,
"percentageTokens": 4.68,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/TransferProgressView.swift": {
"lines": 108,
"tokens": 873,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/SupportRequestTextView.swift": {
"lines": 145,
"tokens": 979,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/ReminderView.swift": {
"lines": 115,
"tokens": 891,
"sources": 1,
"clones": 1,
"duplicatedLines": 10,
"duplicatedTokens": 79,
"percentage": 8.7,
"percentageTokens": 8.87,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/QuotedReplyPreview.swift": {
"lines": 95,
"tokens": 669,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/QRCodeView.swift": {
"lines": 137,
"tokens": 1047,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/PhotoGridViewCell.swift": {
"lines": 191,
"tokens": 1496,
"sources": 1,
"clones": 1,
"duplicatedLines": 12,
"duplicatedTokens": 102,
"percentage": 6.28,
"percentageTokens": 6.82,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/NeverClearView.swift": {
"lines": 8,
"tokens": 61,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/NameCollisionReviewCell.swift": {
"lines": 299,
"tokens": 2646,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/MockConversationView.swift": {
"lines": 390,
"tokens": 2834,
"sources": 1,
"clones": 4,
"duplicatedLines": 154,
"duplicatedTokens": 976,
"percentage": 39.49,
"percentageTokens": 34.44,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/LottieToggleButton.swift": {
"lines": 67,
"tokens": 481,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/JoinGroupCallPill.swift": {
"lines": 100,
"tokens": 786,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/GroupTableViewCell.swift": {
"lines": 73,
"tokens": 608,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/GetStartedBannerCell.swift": {
"lines": 143,
"tokens": 1163,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/ExpirationNagView.swift": {
"lines": 22,
"tokens": 228,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/EmojiMoodPickerView.swift": {
"lines": 126,
"tokens": 1038,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/DismissableTextField.swift": {
"lines": 61,
"tokens": 449,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/ContactCell.swift": {
"lines": 170,
"tokens": 1530,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/CircularProgressView.swift": {
"lines": 104,
"tokens": 918,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/CaptionView.swift": {
"lines": 171,
"tokens": 1191,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/AvatarTableViewCell.swift": {
"lines": 67,
"tokens": 513,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"views/AnimatedProgressView.swift": {
"lines": 178,
"tokens": 1325,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/VolumeButtons.swift": {
"lines": 242,
"tokens": 1787,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/TextFieldHelper.swift": {
"lines": 102,
"tokens": 662,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/OWSCellAccessibilityCustomAction.swift": {
"lines": 21,
"tokens": 158,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/OWSAnalytics.swift": {
"lines": 17,
"tokens": 242,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/Dependencies+MainApp.swift": {
"lines": 109,
"tokens": 603,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/ContactSupportAlert.swift": {
"lines": 113,
"tokens": 1247,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"util/AppUpdateNag.swift": {
"lines": 258,
"tokens": 1899,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"network/GiphyDownloader.swift": {
"lines": 10,
"tokens": 49,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"network/GiphyAPI.swift": {
"lines": 493,
"tokens": 3942,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"environment/SignalApp.swift": {
"lines": 31,
"tokens": 229,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"environment/PushRegistrationManager.swift": {
"lines": 277,
"tokens": 1930,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"environment/AppEnvironment.swift": {
"lines": 88,
"tokens": 526,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ViewOnceMessageViewController.swift": {
"lines": 445,
"tokens": 3136,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/SendMessageFlow.swift": {
"lines": 649,
"tokens": 4998,
"sources": 1,
"clones": 4,
"duplicatedLines": 80,
"duplicatedTokens": 612,
"percentage": 12.33,
"percentageTokens": 12.24,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/SafetyNumberConfirmationSheet.swift": {
"lines": 587,
"tokens": 5093,
"sources": 1,
"clones": 3,
"duplicatedLines": 82,
"duplicatedTokens": 749,
"percentage": 13.97,
"percentageTokens": 14.71,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/OWSPinSetupViewController.swift": {
"lines": 760,
"tokens": 6217,
"sources": 1,
"clones": 1,
"duplicatedLines": 11,
"duplicatedTokens": 113,
"percentage": 1.45,
"percentageTokens": 1.82,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/OWSPinReminderViewController.swift": {
"lines": 370,
"tokens": 3120,
"sources": 1,
"clones": 12,
"duplicatedLines": 260,
"duplicatedTokens": 2205,
"percentage": 70.27,
"percentageTokens": 70.67,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/OWSPinConfirmationViewController.swift": {
"lines": 338,
"tokens": 2789,
"sources": 1,
"clones": 9,
"duplicatedLines": 225,
"duplicatedTokens": 1893,
"percentage": 66.57,
"percentageTokens": 67.87,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/OWSImagePickerController.swift": {
"lines": 9,
"tokens": 47,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MessageReactionPicker.swift": {
"lines": 198,
"tokens": 1970,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MessageDetailViewController.swift": {
"lines": 958,
"tokens": 7134,
"sources": 1,
"clones": 4,
"duplicatedLines": 182,
"duplicatedTokens": 1201,
"percentage": 19,
"percentageTokens": 16.83,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/MessageActionsViewController.swift": {
"lines": 497,
"tokens": 4025,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/LongTextViewController.swift": {
"lines": 216,
"tokens": 1524,
"sources": 1,
"clones": 1,
"duplicatedLines": 13,
"duplicatedTokens": 109,
"percentage": 6.02,
"percentageTokens": 7.15,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/LocationPicker.swift": {
"lines": 532,
"tokens": 4630,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/LoadingViewController.swift": {
"lines": 163,
"tokens": 1182,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/InviteFlow.swift": {
"lines": 328,
"tokens": 2918,
"sources": 1,
"clones": 2,
"duplicatedLines": 16,
"duplicatedTokens": 214,
"percentage": 4.88,
"percentageTokens": 7.33,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GroupMigrationActionSheet.swift": {
"lines": 692,
"tokens": 5533,
"sources": 1,
"clones": 2,
"duplicatedLines": 30,
"duplicatedTokens": 260,
"percentage": 4.34,
"percentageTokens": 4.7,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GroupLinkPromotionActionSheet.swift": {
"lines": 224,
"tokens": 1656,
"sources": 1,
"clones": 1,
"duplicatedLines": 14,
"duplicatedTokens": 115,
"percentage": 6.25,
"percentageTokens": 6.94,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GroupInviteLinksUI.swift": {
"lines": 389,
"tokens": 3172,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/GetStartedBannerViewController.swift": {
"lines": 339,
"tokens": 2814,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ForwardMessageNavigationController.swift": {
"lines": 509,
"tokens": 3960,
"sources": 1,
"clones": 4,
"duplicatedLines": 80,
"duplicatedTokens": 612,
"percentage": 15.72,
"percentageTokens": 15.45,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/CropScaleImageViewController.swift": {
"lines": 509,
"tokens": 4321,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ContactsPicker.swift": {
"lines": 383,
"tokens": 3269,
"sources": 1,
"clones": 1,
"duplicatedLines": 8,
"duplicatedTokens": 75,
"percentage": 2.09,
"percentageTokens": 2.29,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ContactViewController.swift": {
"lines": 658,
"tokens": 5712,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ContactShareViewHelper.swift": {
"lines": 214,
"tokens": 1629,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ColorPickerViewController.swift": {
"lines": 239,
"tokens": 1824,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/CameraFirstNavigationController.swift": {
"lines": 116,
"tokens": 894,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/AddContactShareToExistingContactViewController.swift": {
"lines": 141,
"tokens": 980,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"ViewControllers/ActionSheetContentBuilder.swift": {
"lines": 51,
"tokens": 434,
"sources": 1,
"clones": 1,
"duplicatedLines": 16,
"duplicatedTokens": 145,
"percentage": 31.37,
"percentageTokens": 33.41,
"newDuplicatedLines": 0,
"newClones": 0
},
"UserInterface/OWSLayerView.swift": {
"lines": 45,
"tokens": 274,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Models/ThreadMapping.swift": {
"lines": 696,
"tokens": 5822,
"sources": 1,
"clones": 6,
"duplicatedLines": 74,
"duplicatedTokens": 802,
"percentage": 10.63,
"percentageTokens": 13.78,
"newDuplicatedLines": 0,
"newClones": 0
},
"Models/PhoneNumberValidator.swift": {
"lines": 42,
"tokens": 342,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Models/MessageActions.swift": {
"lines": 173,
"tokens": 1729,
"sources": 1,
"clones": 8,
"duplicatedLines": 106,
"duplicatedTokens": 962,
"percentage": 61.27,
"percentageTokens": 55.64,
"newDuplicatedLines": 0,
"newClones": 0
},
"Models/CompareSafetyNumbersActivity.swift": {
"lines": 104,
"tokens": 880,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Models/AccountManager.swift": {
"lines": 499,
"tokens": 3975,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Jobs/SyncPushTokensJob.swift": {
"lines": 114,
"tokens": 969,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Jobs/SessionResetJob.swift": {
"lines": 175,
"tokens": 1304,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Jobs/ConversationConfigurationSyncOperation.swift": {
"lines": 101,
"tokens": 736,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/SplashViewController.swift": {
"lines": 95,
"tokens": 668,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/MegaphoneView.swift": {
"lines": 354,
"tokens": 3017,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Experience Upgrades/ExperienceUpgradeManager.swift": {
"lines": 242,
"tokens": 1929,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/SignalCall.swift": {
"lines": 317,
"tokens": 2677,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/CallAudioService.swift": {
"lines": 603,
"tokens": 4419,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"Calls/AudioSource.swift": {
"lines": 79,
"tokens": 550,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"UserNotificationActionHandler.swift": {
"lines": 72,
"tokens": 614,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"UIStoryboard+OWS.swift": {
"lines": 11,
"tokens": 77,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"UIResponder+OWS.swift": {
"lines": 14,
"tokens": 115,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"UIApplication+OWS.swift": {
"lines": 30,
"tokens": 251,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
},
"NotificationActionHandler.swift": {
"lines": 216,
"tokens": 2176,
"sources": 1,
"clones": 6,
"duplicatedLines": 54,
"duplicatedTokens": 652,
"percentage": 25,
"percentageTokens": 29.96,
"newDuplicatedLines": 0,
"newClones": 0
},
"ConversationSearch.swift": {
"lines": 340,
"tokens": 2668,
"sources": 1,
"clones": 0,
"duplicatedLines": 0,
"duplicatedTokens": 0,
"percentage": 0,
"percentageTokens": 0,
"newDuplicatedLines": 0,
"newClones": 0
}
},
"total": {
"lines": 81131,
"tokens": 637041,
"sources": 322,
"clones": 134,
"duplicatedLines": 2428,
"duplicatedTokens": 19817,
"percentage": 2.99,
"percentageTokens": 3.11,
"newDuplicatedLines": 0,
"newClones": 0
}
}
},
"total": {
"lines": 81131,
"tokens": 637041,
"sources": 322,
"clones": 134,
"duplicatedLines": 2428,
"duplicatedTokens": 19817,
"percentage": 2.99,
"percentageTokens": 3.11,
"newDuplicatedLines": 0,
"newClones": 0
}
},
"duplicates": [
{
"format": "swift",
"lines": 26,
"fragment": "super.init(itemModel: itemModel)\n }\n\n public func configure(cellView: UIView,\n cellMeasurement: CVCellMeasurement,\n componentDelegate: CVComponentDelegate,\n cellSelection: CVCellSelection,\n swipeToReplyState: CVSwipeToReplyState,\n componentView: CVComponentView) {\n\n configureForRendering(componentView: componentView,\n cellMeasurement: cellMeasurement,\n componentDelegate: componentDelegate)\n\n let rootView = componentView.rootView\n if rootView.superview == nil {\n owsAssertDebug(cellView.layoutMargins == .zero)\n owsAssertDebug(cellView.subviews.isEmpty)\n\n cellView.addSubview(rootView)\n rootView.autoPinEdgesToSuperviewMargins()\n }\n }\n\n public func buildComponentView(componentDelegate: CVComponentDelegate) -> CVComponentView {\n CVComponentViewTypingIndicator",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentTypingIndicator.swift",
"start": 22,
"end": 47,
"startLoc": {
"line": 22,
"column": 9,
"position": 108
},
"endLoc": {
"line": 47,
"column": 31,
"position": 288
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentUnreadIndicator.swift",
"start": 17,
"end": 42,
"startLoc": {
"line": 17,
"column": 9,
"position": 76
},
"endLoc": {
"line": 42,
"column": 31,
"position": 256
}
}
},
{
"format": "swift",
"lines": 21,
"fragment": "super.init(itemModel: itemModel)\n }\n\n public func configure(cellView: UIView,\n cellMeasurement: CVCellMeasurement,\n componentDelegate: CVComponentDelegate,\n cellSelection: CVCellSelection,\n swipeToReplyState: CVSwipeToReplyState,\n componentView: CVComponentView) {\n\n configureForRendering(componentView: componentView,\n cellMeasurement: cellMeasurement,\n componentDelegate: componentDelegate)\n\n let rootView = componentView.rootView\n if rootView.superview == nil {\n owsAssertDebug(cellView.layoutMargins == .zero)\n owsAssertDebug(cellView.subviews.isEmpty)\n\n cellView.addSubview(rootView)\n cellView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentSystemMessage.swift",
"start": 24,
"end": 44,
"startLoc": {
"line": 24,
"column": 9,
"position": 136
},
"endLoc": {
"line": 44,
"column": 9,
"position": 282
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentUnreadIndicator.swift",
"start": 17,
"end": 37,
"startLoc": {
"line": 17,
"column": 9,
"position": 76
},
"endLoc": {
"line": 37,
"column": 9,
"position": 222
}
}
},
{
"format": "swift",
"lines": 28,
"fragment": "super.init(itemModel: itemModel)\n }\n\n public func configure(cellView: UIView,\n cellMeasurement: CVCellMeasurement,\n componentDelegate: CVComponentDelegate,\n cellSelection: CVCellSelection,\n swipeToReplyState: CVSwipeToReplyState,\n componentView: CVComponentView) {\n\n configureForRendering(componentView: componentView,\n cellMeasurement: cellMeasurement,\n componentDelegate: componentDelegate)\n\n let rootView = componentView.rootView\n if rootView.superview == nil {\n owsAssertDebug(cellView.layoutMargins == .zero)\n owsAssertDebug(cellView.subviews.isEmpty)\n\n cellView.addSubview(rootView)\n cellView.layoutMargins = cellLayoutMargins\n rootView.autoPinEdgesToSuperviewMargins()\n }\n }\n\n private var cellLayoutMargins: UIEdgeInsets {\n UIEdgeInsets(top: 0,\n leading: conversationStyle.headerGutterLeading",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentDateHeader.swift",
"start": 24,
"end": 51,
"startLoc": {
"line": 24,
"column": 9,
"position": 124
},
"endLoc": {
"line": 51,
"column": 20,
"position": 319
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentUnreadIndicator.swift",
"start": 17,
"end": 51,
"startLoc": {
"line": 17,
"column": 9,
"position": 76
},
"endLoc": {
"line": 51,
"column": 23,
"position": 331
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": ")\n\n let leadingSpacer = UIView.hStretchingSpacer()\n let trailingSpacer = UIView.hStretchingSpacer()\n\n hStackView.addArrangedSubview(leadingSpacer)\n hStackView.addArrangedSubview(contentView)\n hStackView.addArrangedSubview(trailingSpacer)\n\n leadingSpacer.autoMatch(.width, to: .width, of: trailingSpacer)\n }",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentDateHeader.swift",
"start": 84,
"end": 94,
"startLoc": {
"line": 84,
"column": 13,
"position": 581
},
"endLoc": {
"line": 94,
"column": 2,
"position": 659
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentUnreadIndicator.swift",
"start": 66,
"end": 77,
"startLoc": {
"line": 66,
"column": 11,
"position": 455
},
"endLoc": {
"line": 77,
"column": 12,
"position": 534
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "()\n }\n\n private var bodyTextColor: UIColor {\n guard let message = interaction as? TSMessage else {\n return .black\n }\n return conversationStyle.bubbleTextColor(message: message)\n }\n\n public func configureForRendering(componentView componentViewParam: CVComponentView,\n cellMeasurement: CVCellMeasurement,\n componentDelegate: CVComponentDelegate) {\n guard let componentView = componentViewParam as? CVComponentViewBodyMedia",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentBodyMedia.swift",
"start": 47,
"end": 60,
"startLoc": {
"line": 47,
"column": 25,
"position": 289
},
"endLoc": {
"line": 60,
"column": 25,
"position": 399
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/CV/CVComponents/CVComponentSenderName.swift",
"start": 19,
"end": 32,
"startLoc": {
"line": 19,
"column": 26,
"position": 104
},
"endLoc": {
"line": 32,
"column": 26,
"position": 214
}
}
},
{
"format": "swift",
"lines": 21,
"fragment": ": UIViewControllerAnimatedTransitioning {\n func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {\n return kIsDebuggingMediaPresentationAnimations ? 1.5 : 0.15\n }\n\n func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {\n let containerView = transitionContext.containerView\n\n guard let fromVC = transitionContext.viewController(forKey: .from) else {\n owsFailDebug(\"fromVC was unexpectedly nil\")\n transitionContext.completeTransition(false)\n return\n }\n\n let fromContextProvider: MediaPresentationContextProvider\n switch fromVC {\n case let contextProvider as MediaPresentationContextProvider:\n fromContextProvider = contextProvider\n case let navController as UINavigationController:\n guard let contextProvider = navController.topViewController as? MediaPresentationContextProvider else {\n owsFailDebug(\"unexpected context: ",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaDismissAnimationController.swift",
"start": 27,
"end": 47,
"startLoc": {
"line": 27,
"column": 32,
"position": 187
},
"endLoc": {
"line": 47,
"column": 22,
"position": 374
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaZoomAnimationController.swift",
"start": 19,
"end": 39,
"startLoc": {
"line": 19,
"column": 29,
"position": 89
},
"endLoc": {
"line": 39,
"column": 30,
"position": 276
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": ".topViewController))\")\n transitionContext.completeTransition(false)\n return\n }\n fromContextProvider = contextProvider\n default:\n owsFailDebug(\"unexpected fromVC: \\(fromVC)\")\n transitionContext.completeTransition(false)\n return\n }\n\n guard let fromMediaContext = fromContextProvider.mediaPresentationContext(item: item, in: containerView) else {\n owsFailDebug(\"fromPresentationContext was unexpectedly nil\")\n transitionContext.completeTransition(false)\n return\n }\n self",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaDismissAnimationController.swift",
"start": 47,
"end": 63,
"startLoc": {
"line": 47,
"column": 15,
"position": 381
},
"endLoc": {
"line": 63,
"column": 5,
"position": 488
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaZoomAnimationController.swift",
"start": 46,
"end": 63,
"startLoc": {
"line": 46,
"column": 21,
"position": 355
},
"endLoc": {
"line": 63,
"column": 6,
"position": 463
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "containerView.addSubview(transitionView)\n transitionView.frame = fromMediaContext.presentationFrame\n\n let fromTransitionalOverlayView: UIView?\n if let (overlayView, overlayViewFrame) = fromContextProvider.snapshotOverlayView(in: containerView) {\n fromTransitionalOverlayView = overlayView\n containerView.addSubview(overlayView)\n overlayView.frame = overlayViewFrame\n } else {\n fromTransitionalOverlayView = nil\n }\n\n assert",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaDismissAnimationController.swift",
"start": 132,
"end": 144,
"startLoc": {
"line": 132,
"column": 9,
"position": 1055
},
"endLoc": {
"line": 144,
"column": 7,
"position": 1152
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/Transitions/MediaZoomAnimationController.swift",
"start": 108,
"end": 120,
"startLoc": {
"line": 108,
"column": 9,
"position": 813
},
"endLoc": {
"line": 120,
"column": 4,
"position": 910
}
}
},
{
"format": "swift",
"lines": 20,
"fragment": "super.init(nibName: nil, bundle: nil)\n modalPresentationStyle = .custom\n transitioningDelegate = self\n }\n\n required init?(coder aDecoder: NSCoder) {\n fatalError(\"init(coder:) has not been implemented\")\n }\n\n // MARK: -\n\n override public func loadView() {\n view = UIView()\n view.backgroundColor = .clear\n\n view.addSubview(contentView)\n contentView.autoPinEdge(toSuperviewEdge: .bottom)\n contentView.autoHCenterInSuperview()\n contentView.autoMatch(.height, to: .height, of: view, withOffset: 0, relation: .lessThanOrEqual)\n contentView.backgroundColor = Theme.isDarkThemeEnabled",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 20,
"end": 39,
"startLoc": {
"line": 20,
"column": 9,
"position": 135
},
"endLoc": {
"line": 39,
"column": 19,
"position": 304
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 34,
"end": 53,
"startLoc": {
"line": 34,
"column": 9,
"position": 243
},
"endLoc": {
"line": 53,
"column": 27,
"position": 412
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ")\n\n let cornerRadius: CGFloat = 16\n let path = UIBezierPath(\n roundedRect: contentView.bounds,\n byRoundingCorners: [.topLeft, .topRight],\n cornerRadii: CGSize(square: cornerRadius)\n )\n let shapeLayer = CAShapeLayer()\n shapeLayer.path = path.cgPath\n contentView.layer.mask = shapeLayer\n }\n\n @objc func didTapBackdrop",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 81,
"end": 94,
"startLoc": {
"line": 81,
"column": 2,
"position": 635
},
"endLoc": {
"line": 94,
"column": 15,
"position": 740
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 104,
"end": 120,
"startLoc": {
"line": 104,
"column": 2,
"position": 713
},
"endLoc": {
"line": 120,
"column": 17,
"position": 823
}
}
},
{
"format": "swift",
"lines": 24,
"fragment": "var minimizedHeight: CGFloat {\n return min(maximizedHeight, 346)\n }\n var maximizedHeight: CGFloat {\n return CurrentAppContext().frame.height - topLayoutGuide.length - 32\n }\n\n let maxAnimationDuration: TimeInterval = 0.2\n var startingHeight: CGFloat?\n var startingTranslation: CGFloat?\n\n func setupInteractiveSizing() {\n heightConstraint = contentView.autoSetDimension(.height, toSize: minimizedHeight)\n\n // Create a pan gesture to handle when the user interacts with the\n // view outside of the collection view.\n let panGestureRecognizer = DirectionalPanGestureRecognizer(direction: .vertical, target: self, action: #selector(handlePan))\n view.addGestureRecognizer(panGestureRecognizer)\n panGestureRecognizer.delegate = self\n\n // We also want to handle the pan gesture for the collection view,\n // so we can do a nice scroll to dismiss gesture, and so we can\n // transfer any initial scrolling into maximizing the view.\n collectionView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 103,
"end": 126,
"startLoc": {
"line": 103,
"column": 5,
"position": 797
},
"endLoc": {
"line": 126,
"column": 15,
"position": 981
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 171,
"end": 195,
"startLoc": {
"line": 171,
"column": 5,
"position": 1257
},
"endLoc": {
"line": 195,
"column": 19,
"position": 1444
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "handle.backgroundColor = .ows_whiteAlpha80\n handle.autoSetDimensions(to: CGSize(width: 56, height: 5))\n handle.layer.cornerRadius = 5 / 2\n view.addSubview(handle)\n handle.autoHCenterInSuperview()\n handle.autoPinEdge(.bottom, to: .top, of: contentView, withOffset: -8)\n }\n\n @objc func handlePan(_ sender: UIPanGestureRecognizer) {\n let isCollectionViewPanGesture",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 128,
"end": 137,
"startLoc": {
"line": 128,
"column": 9,
"position": 1002
},
"endLoc": {
"line": 137,
"column": 27,
"position": 1117
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 197,
"end": 206,
"startLoc": {
"line": 197,
"column": 9,
"position": 1474
},
"endLoc": {
"line": 206,
"column": 22,
"position": 1589
}
}
},
{
"format": "swift",
"lines": 39,
"fragment": ".alpha = 1 - (startingHeight - newHeight) / startingHeight\n }\n\n // Update our height to reflect the new position\n heightConstraint?.constant = newHeight\n view.layoutIfNeeded()\n case .ended, .cancelled, .failed:\n guard let startingHeight = startingHeight else { break }\n\n let dismissThreshold = startingHeight * 0.5\n let growThreshold = startingHeight * 1.5\n let velocityThreshold: CGFloat = 500\n\n let currentHeight = contentView.height\n let currentVelocity = sender.velocity(in: view).y\n\n enum CompletionState { case growing, dismissing, cancelling }\n let completionState: CompletionState\n\n if abs(currentVelocity) >= velocityThreshold {\n completionState = currentVelocity < 0 ? .growing : .dismissing\n } else if currentHeight >= growThreshold {\n completionState = .growing\n } else if currentHeight <= dismissThreshold {\n completionState = .dismissing\n } else {\n completionState = .cancelling\n }\n\n let finalHeight: CGFloat\n switch completionState {\n case .dismissing:\n finalHeight = 0\n case .growing:\n finalHeight = maximizedHeight\n case .cancelling:\n finalHeight = startingHeight\n\n if",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 166,
"end": 204,
"startLoc": {
"line": 166,
"column": 2,
"position": 1315
},
"endLoc": {
"line": 204,
"column": 3,
"position": 1652
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 235,
"end": 272,
"startLoc": {
"line": 235,
"column": 13,
"position": 1786
},
"endLoc": {
"line": 272,
"column": 2,
"position": 2122
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": "}\n\n let remainingDistance = finalHeight - currentHeight\n\n // Calculate the time to complete the animation if we want to preserve\n // the user's velocity. If this time is too slow (e.g. the user was scrolling\n // very slowly) we'll default to `maxAnimationDuration`\n let remainingTime = TimeInterval(abs(remainingDistance / currentVelocity))\n\n UIView.animate(withDuration: min(remainingTime, maxAnimationDuration), delay: 0, options: .curveEaseOut, animations: {\n if remainingDistance < 0 {\n self.contentView.frame.origin.y -= remainingDistance\n self.handle.frame.origin.y -= remainingDistance\n } else {\n self.heightConstraint?.constant = finalHeight\n self.view.layoutIfNeeded()\n }\n\n self.backdropView?",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 207,
"end": 225,
"startLoc": {
"line": 207,
"column": 13,
"position": 1678
},
"endLoc": {
"line": 225,
"column": 2,
"position": 1838
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 272,
"end": 290,
"startLoc": {
"line": 272,
"column": 13,
"position": 2122
},
"endLoc": {
"line": 290,
"column": 2,
"position": 2282
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": ".panGestureRecognizer else { return false }\n\n if startingTranslation == nil {\n startingTranslation = sender.translation(in: view).y\n }\n\n if startingHeight == nil {\n startingHeight = contentView.height\n }\n\n return true\n }\n\n func resetInteractiveTransition() {\n startingTranslation = nil\n startingHeight = nil\n collectionView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 253,
"end": 269,
"startLoc": {
"line": 253,
"column": 15,
"position": 2052
},
"endLoc": {
"line": 269,
"column": 15,
"position": 2155
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 315,
"end": 331,
"startLoc": {
"line": 315,
"column": 24,
"position": 2490
},
"endLoc": {
"line": 331,
"column": 24,
"position": 2593
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": ": UIGestureRecognizerDelegate {\n func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UITapGestureRecognizer:\n let point = gestureRecognizer.location(in: view)\n guard !contentView.frame.contains(point) else { return false }\n return true\n default:\n return true\n }\n }\n\n func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UIPanGestureRecognizer:\n return collectionView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 303,
"end": 318,
"startLoc": {
"line": 303,
"column": 17,
"position": 2435
},
"endLoc": {
"line": 318,
"column": 15,
"position": 2583
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 583,
"end": 598,
"startLoc": {
"line": 583,
"column": 21,
"position": 4539
},
"endLoc": {
"line": 598,
"column": 24,
"position": 4687
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": "presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 1\n }, completion: nil)\n }\n\n override func dismissalTransitionWillBegin() {\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 0\n }, completion: nil",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 335,
"end": 343,
"startLoc": {
"line": 335,
"column": 9,
"position": 2684
},
"endLoc": {
"line": 343,
"column": 4,
"position": 2773
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 626,
"end": 634,
"startLoc": {
"line": 626,
"column": 9,
"position": 4903
},
"endLoc": {
"line": 634,
"column": 2,
"position": 4992
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ")\n }\n\n override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n guard let presentedView = presentedView else { return }\n coordinator.animate(alongsideTransition: { _ in\n presentedView.frame = self.frameOfPresentedViewInContainerView\n presentedView.layoutIfNeeded()\n }, completion: nil)\n }\n}\n\nextension EmojiPickerSheet",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 343,
"end": 356,
"startLoc": {
"line": 343,
"column": 4,
"position": 2774
},
"endLoc": {
"line": 356,
"column": 17,
"position": 2891
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 636,
"end": 649,
"startLoc": {
"line": 636,
"column": 2,
"position": 5010
},
"endLoc": {
"line": 649,
"column": 21,
"position": 5127
}
}
},
{
"format": "swift",
"lines": 23,
"fragment": "()\n\n init(attachmentStream: TSAttachmentStream) {\n self.attachmentStream = attachmentStream\n }\n\n var mediaView: UIView {\n imageView\n }\n\n var isLoaded: Bool {\n imageView.image != nil\n }\n\n var cacheKey: String {\n attachmentStream.uniqueId\n }\n\n func loadMedia() -> Promise<AnyObject> {\n guard attachmentStream.isValidImage else {\n return Promise(error: ReusableMediaError.invalidMedia)\n }\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 323,
"end": 345,
"startLoc": {
"line": 323,
"column": 12,
"position": 1922
},
"endLoc": {
"line": 345,
"column": 4,
"position": 2054
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 269,
"end": 291,
"startLoc": {
"line": 269,
"column": 20,
"position": 1560
},
"endLoc": {
"line": 291,
"column": 6,
"position": 1692
}
}
},
{
"format": "swift",
"lines": 22,
"fragment": "}\n\n func applyMedia(_ media: AnyObject) {\n AssertIsOnMainThread()\n\n guard let image = media as? UIImage else {\n owsFailDebug(\"Media has unexpected type: \\(type(of: media))\")\n return\n }\n imageView.image = image\n }\n\n func unloadMedia() {\n AssertIsOnMainThread()\n\n imageView.image = nil\n }\n}\n\n// MARK: -\n\nclass MediaViewAdapterVideo",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 357,
"end": 378,
"startLoc": {
"line": 357,
"column": 5,
"position": 2164
},
"endLoc": {
"line": 378,
"column": 22,
"position": 2277
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 244,
"end": 265,
"startLoc": {
"line": 244,
"column": 5,
"position": 1412
},
"endLoc": {
"line": 265,
"column": 25,
"position": 1525
}
}
},
{
"format": "swift",
"lines": 24,
"fragment": ": MediaViewAdapterSwift {\n\n public let shouldBeRenderedByYY = false\n let attachmentStream: TSAttachmentStream\n let imageView = UIImageView()\n\n init(attachmentStream: TSAttachmentStream) {\n self.attachmentStream = attachmentStream\n }\n\n var mediaView: UIView {\n imageView\n }\n\n var isLoaded: Bool {\n imageView.image != nil\n }\n\n var cacheKey: String {\n attachmentStream.uniqueId\n }\n\n func loadMedia() -> Promise<AnyObject> {\n guard attachmentStream.isValidVideo",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 378,
"end": 401,
"startLoc": {
"line": 378,
"column": 22,
"position": 2278
},
"endLoc": {
"line": 401,
"column": 13,
"position": 2421
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 319,
"end": 288,
"startLoc": {
"line": 319,
"column": 22,
"position": 1888
},
"endLoc": {
"line": 288,
"column": 13,
"position": 1669
}
}
},
{
"format": "swift",
"lines": 37,
"fragment": "else {\n return Promise(error: ReusableMediaError.invalidMedia)\n }\n let (promise, resolver) = Promise<AnyObject>.pending()\n let possibleThumbnail = attachmentStream.thumbnailImageLarge(success: { (image) in\n resolver.fulfill(image)\n }, failure: {\n resolver.reject(OWSAssertionError(\"Could not load thumbnail\"))\n })\n // TSAttachmentStream's thumbnail methods return a UIImage sync\n // if the thumbnail already exists. Otherwise, the callbacks are invoked async.\n if let thumbnail = possibleThumbnail {\n resolver.fulfill(thumbnail)\n }\n return promise\n }\n\n func applyMedia(_ media: AnyObject) {\n AssertIsOnMainThread()\n\n guard let image = media as? UIImage else {\n owsFailDebug(\"Media has unexpected type: \\(type(of: media))\")\n return\n }\n imageView.image = image\n }\n\n func unloadMedia() {\n AssertIsOnMainThread()\n\n imageView.image = nil\n }\n}\n\n// MARK: -\n\n@objc",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 401,
"end": 437,
"startLoc": {
"line": 401,
"column": 2,
"position": 2423
},
"endLoc": {
"line": 437,
"column": 6,
"position": 2665
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Cells/ReusableMediaView.swift",
"start": 342,
"end": 265,
"startLoc": {
"line": 342,
"column": 2,
"position": 2033
},
"endLoc": {
"line": 265,
"column": 6,
"position": 1523
}
}
},
{
"format": "swift",
"lines": 27,
"fragment": ")\n\n navigationItem.leftBarButtonItem = UIBarButtonItem(\n barButtonSystemItem: .cancel,\n target: self,\n action: #selector(didTapCancel),\n accessibilityIdentifier: \"cancel_button\"\n )\n\n if hasUnsavedChanges {\n navigationItem.rightBarButtonItem = UIBarButtonItem(\n barButtonSystemItem: .done,\n target: self,\n action: #selector(didTapDone),\n accessibilityIdentifier: \"done_button\"\n )\n } else {\n navigationItem.rightBarButtonItem = nil\n }\n }\n\n public override func viewWillAppear(_ animated: Bool) {\n super.viewWillAppear(animated)\n\n updateNavigation()\n\n firstTextField",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileNameViewController.swift",
"start": 71,
"end": 97,
"startLoc": {
"line": 71,
"column": 35,
"position": 470
},
"endLoc": {
"line": 97,
"column": 15,
"position": 629
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/UsernameViewController.swift",
"start": 62,
"end": 87,
"startLoc": {
"line": 62,
"column": 35,
"position": 384
},
"endLoc": {
"line": 87,
"column": 2,
"position": 542
}
}
},
{
"format": "swift",
"lines": 20,
"fragment": "}\n\n private func nameCell(textField: UITextField) -> UITableViewCell {\n let cell = OWSTableItem.newCell()\n\n cell.selectionStyle = .none\n\n textField.font = .ows_dynamicTypeBodyClamped\n textField.textColor = Theme.primaryTextColor\n\n cell.addSubview(textField)\n textField.autoPinEdgesToSuperviewMargins()\n\n return cell\n }\n\n @objc\n func didTapCancel() {\n guard hasUnsavedChanges else {\n dismiss",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileNameViewController.swift",
"start": 164,
"end": 183,
"startLoc": {
"line": 164,
"column": 5,
"position": 1099
},
"endLoc": {
"line": 183,
"column": 8,
"position": 1216
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/UsernameViewController.swift",
"start": 177,
"end": 195,
"startLoc": {
"line": 177,
"column": 5,
"position": 1151
},
"endLoc": {
"line": 195,
"column": 7,
"position": 1267
}
}
},
{
"format": "swift",
"lines": 20,
"fragment": "navigationItem.leftBarButtonItem = UIBarButtonItem(\n barButtonSystemItem: .cancel,\n target: self,\n action: #selector(didTapCancel),\n accessibilityIdentifier: \"cancel_button\"\n )\n\n if hasUnsavedChanges {\n navigationItem.rightBarButtonItem = UIBarButtonItem(\n barButtonSystemItem: .done,\n target: self,\n action: #selector(didTapDone),\n accessibilityIdentifier: \"done_button\"\n )\n } else {\n navigationItem.rightBarButtonItem = nil\n }\n }\n\n func",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/Notifications/NotificationSettingsSoundViewController.swift",
"start": 45,
"end": 64,
"startLoc": {
"line": 45,
"column": 9,
"position": 290
},
"endLoc": {
"line": 64,
"column": 5,
"position": 411
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/UsernameViewController.swift",
"start": 64,
"end": 83,
"startLoc": {
"line": 64,
"column": 9,
"position": 388
},
"endLoc": {
"line": 83,
"column": 7,
"position": 509
}
}
},
{
"format": "swift",
"lines": 24,
"fragment": ": CallObserver {\n func groupCallRemoteDeviceStatesChanged(_ call: SignalCall) {\n AssertIsOnMainThread()\n owsAssertDebug(call.isGroupCall)\n\n reloadData()\n }\n\n func groupCallPeekChanged(_ call: SignalCall) {\n AssertIsOnMainThread()\n owsAssertDebug(call.isGroupCall)\n\n reloadData()\n }\n\n func groupCallEnded(_ call: SignalCall, reason: GroupCallEndReason) {\n AssertIsOnMainThread()\n owsAssertDebug(call.isGroupCall)\n\n reloadData()\n }\n}\n\nextension",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoGrid.swift",
"start": 75,
"end": 98,
"startLoc": {
"line": 75,
"column": 19,
"position": 629
},
"endLoc": {
"line": 98,
"column": 10,
"position": 757
}
},
"secondFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoOverflow.swift",
"start": 138,
"end": 161,
"startLoc": {
"line": 138,
"column": 23,
"position": 1125
},
"endLoc": {
"line": 161,
"column": 6,
"position": 1253
}
}
},
{
"format": "swift",
"lines": 32,
"fragment": ")\n\n override init(frame: CGRect) {\n super.init(frame: frame)\n\n contentView.addSubview(memberView)\n memberView.autoPinEdgesToSuperviewEdges()\n\n contentView.layer.cornerRadius = 10\n contentView.clipsToBounds = true\n }\n\n func configure(call: SignalCall, device: RemoteDeviceState) {\n memberView.configure(call: call, device: device)\n }\n\n required init?(coder: NSCoder) {\n fatalError(\"init(coder:) has not been implemented\")\n }\n\n func cleanupVideoViews() {\n memberView.cleanupVideoViews()\n }\n\n func configureRemoteVideo(device: RemoteDeviceState) {\n memberView.configureRemoteVideo(device: device)\n }\n\n func setMemberViewDelegate(_ delegate: GroupCallMemberViewDelegate?) {\n memberView.delegate = delegate\n }\n}",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoGrid.swift",
"start": 126,
"end": 157,
"startLoc": {
"line": 126,
"column": 10,
"position": 987
},
"endLoc": {
"line": 157,
"column": 2,
"position": 1195
}
},
"secondFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoOverflow.swift",
"start": 163,
"end": 194,
"startLoc": {
"line": 163,
"column": 14,
"position": 1289
},
"endLoc": {
"line": 194,
"column": 2,
"position": 1497
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ") }\n\n // MARK: -\n\n override public func loadView() {\n view = UIView()\n view.backgroundColor = .clear\n\n view.addSubview(contentView)\n contentView.autoPinEdge(toSuperviewEdge: .bottom)\n contentView.autoHCenterInSuperview()\n contentView.autoMatch(.height, to: .height, of: view, withOffset: 0, relation: .lessThanOrEqual)\n\n if",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 30,
"end": 43,
"startLoc": {
"line": 30,
"column": 5,
"position": 197
},
"endLoc": {
"line": 43,
"column": 3,
"position": 303
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 40,
"end": 53,
"startLoc": {
"line": 40,
"column": 40,
"position": 298
},
"endLoc": {
"line": 53,
"column": 12,
"position": 404
}
}
},
{
"format": "swift",
"lines": 24,
"fragment": ")\n }\n\n public override func viewDidLayoutSubviews() {\n super.viewDidLayoutSubviews()\n\n // Ensure the scrollView's layout has completed\n // as we're about to use its bounds to calculate\n // the masking view and contentOffset.\n contentView.layoutIfNeeded()\n\n let cornerRadius: CGFloat = 16\n let path = UIBezierPath(\n roundedRect: contentView.bounds,\n byRoundingCorners: [.topLeft, .topRight],\n cornerRadii: CGSize(square: cornerRadius)\n )\n let shapeLayer = CAShapeLayer()\n shapeLayer.path = path.cgPath\n contentView.layer.mask = shapeLayer\n }\n\n @objc func didTapBackdrop(_ sender: UITapGestureRecognizer) {\n dismiss",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 77,
"end": 100,
"startLoc": {
"line": 77,
"column": 2,
"position": 621
},
"endLoc": {
"line": 100,
"column": 8,
"position": 780
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 95,
"end": 95,
"startLoc": {
"line": 95,
"column": 5,
"position": 672
},
"endLoc": {
"line": 95,
"column": 18,
"position": 753
}
}
},
{
"format": "swift",
"lines": 31,
"fragment": "dismiss(animated: true)\n }\n\n // MARK: - Resize / Interactive Dismiss\n\n var heightConstraint: NSLayoutConstraint?\n let maxWidth: CGFloat = 512\n var minimizedHeight: CGFloat {\n return min(maximizedHeight, 346)\n }\n var maximizedHeight: CGFloat {\n return CurrentAppContext().frame.height - topLayoutGuide.length - 32\n }\n\n let maxAnimationDuration: TimeInterval = 0.2\n var startingHeight: CGFloat?\n var startingTranslation: CGFloat?\n\n func setupInteractiveSizing() {\n heightConstraint = contentView.autoSetDimension(.height, toSize: minimizedHeight)\n\n // Create a pan gesture to handle when the user interacts with the\n // view outside of the collection view.\n let panGestureRecognizer = DirectionalPanGestureRecognizer(direction: .vertical, target: self, action: #selector(handlePan))\n view.addGestureRecognizer(panGestureRecognizer)\n panGestureRecognizer.delegate = self\n\n // We also want to handle the pan gesture for the collection view,\n // so we can do a nice scroll to dismiss gesture, and so we can\n // transfer any initial scrolling into maximizing the view.\n tableView",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 100,
"end": 130,
"startLoc": {
"line": 100,
"column": 9,
"position": 780
},
"endLoc": {
"line": 130,
"column": 10,
"position": 1002
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 96,
"end": 195,
"startLoc": {
"line": 96,
"column": 9,
"position": 759
},
"endLoc": {
"line": 195,
"column": 19,
"position": 1444
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": ".panGestureRecognizer.addTarget(self, action: #selector(handlePan))\n\n handle.backgroundColor = .ows_whiteAlpha80\n handle.autoSetDimensions(to: CGSize(width: 56, height: 5))\n handle.layer.cornerRadius = 5 / 2\n view.addSubview(handle)\n handle.autoHCenterInSuperview()\n handle.autoPinEdge(.bottom, to: .top, of: contentView, withOffset: -8)\n }\n\n @objc func handlePan(_ sender: UIPanGestureRecognizer) {\n let isCollectionViewPanGesture = sender == tableView",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 130,
"end": 141,
"startLoc": {
"line": 130,
"column": 10,
"position": 1003
},
"endLoc": {
"line": 141,
"column": 10,
"position": 1146
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 126,
"end": 137,
"startLoc": {
"line": 126,
"column": 15,
"position": 982
},
"endLoc": {
"line": 137,
"column": 15,
"position": 1125
}
}
},
{
"format": "swift",
"lines": 56,
"fragment": ".showsVerticalScrollIndicator = false\n }\n\n // We may have panned some distance if we were scrolling before we started\n // this interactive transition. Offset the translation we use to move the\n // view by whatever the translation was when we started the interactive\n // portion of the gesture.\n let translation = sender.translation(in: view).y - startingTranslation\n\n var newHeight = startingHeight - translation\n if newHeight > maximizedHeight {\n newHeight = maximizedHeight\n }\n\n // If the height is decreasing, adjust the relevant view's proporitionally\n if newHeight < startingHeight {\n backdropView.alpha = 1 - (startingHeight - newHeight) / startingHeight\n }\n\n // Update our height to reflect the new position\n heightConstraint?.constant = newHeight\n view.layoutIfNeeded()\n case .ended, .cancelled, .failed:\n guard let startingHeight = startingHeight else { break }\n\n let dismissThreshold = startingHeight * 0.5\n let growThreshold = startingHeight * 1.5\n let velocityThreshold: CGFloat = 500\n\n let currentHeight = contentView.height\n let currentVelocity = sender.velocity(in: view).y\n\n enum CompletionState { case growing, dismissing, cancelling }\n let completionState: CompletionState\n\n if abs(currentVelocity) >= velocityThreshold {\n completionState = currentVelocity < 0 ? .growing : .dismissing\n } else if currentHeight >= growThreshold {\n completionState = .growing\n } else if currentHeight <= dismissThreshold {\n completionState = .dismissing\n } else {\n completionState = .cancelling\n }\n\n let finalHeight: CGFloat\n switch completionState {\n case .dismissing:\n finalHeight = 0\n case .growing:\n finalHeight = maximizedHeight\n case .cancelling:\n finalHeight = startingHeight\n\n if isCollectionViewPanGesture {\n tableView",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 154,
"end": 209,
"startLoc": {
"line": 154,
"column": 10,
"position": 1237
},
"endLoc": {
"line": 209,
"column": 10,
"position": 1679
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 219,
"end": 205,
"startLoc": {
"line": 219,
"column": 24,
"position": 1688
},
"endLoc": {
"line": 205,
"column": 15,
"position": 1659
}
}
},
{
"format": "swift",
"lines": 27,
"fragment": ".contentOffset, animated: false)\n }\n }\n\n let remainingDistance = finalHeight - currentHeight\n\n // Calculate the time to complete the animation if we want to preserve\n // the user's velocity. If this time is too slow (e.g. the user was scrolling\n // very slowly) we'll default to `maxAnimationDuration`\n let remainingTime = TimeInterval(abs(remainingDistance / currentVelocity))\n\n UIView.animate(withDuration: min(remainingTime, maxAnimationDuration), delay: 0, options: .curveEaseOut, animations: {\n if remainingDistance < 0 {\n self.contentView.frame.origin.y -= remainingDistance\n self.handle.frame.origin.y -= remainingDistance\n } else {\n self.heightConstraint?.constant = finalHeight\n self.view.layoutIfNeeded()\n }\n\n self.backdropView.alpha = completionState == .dismissing ? 0 : 1\n }) { _ in\n self.heightConstraint?.constant = finalHeight\n self.view.layoutIfNeeded()\n\n if completionState == .dismissing {\n self.dismiss(animated: true)",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 209,
"end": 235,
"startLoc": {
"line": 209,
"column": 10,
"position": 1684
},
"endLoc": {
"line": 235,
"column": 2,
"position": 1931
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Emoji Picker/EmojiPickerSheet.swift",
"start": 205,
"end": 295,
"startLoc": {
"line": 205,
"column": 15,
"position": 1664
},
"endLoc": {
"line": 295,
"column": 2,
"position": 2354
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": ".panGestureRecognizer else { return false }\n\n if startingTranslation == nil {\n startingTranslation = sender.translation(in: view).y\n }\n\n if startingHeight == nil {\n startingHeight = contentView.height\n }\n\n return true\n }\n\n func resetInteractiveTransition() {\n startingTranslation = nil\n startingHeight = nil\n tableView",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 256,
"end": 272,
"startLoc": {
"line": 256,
"column": 10,
"position": 2062
},
"endLoc": {
"line": 272,
"column": 10,
"position": 2165
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 315,
"end": 331,
"startLoc": {
"line": 315,
"column": 24,
"position": 2490
},
"endLoc": {
"line": 331,
"column": 24,
"position": 2593
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": ": UIGestureRecognizerDelegate {\n func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UITapGestureRecognizer:\n let point = gestureRecognizer.location(in: view)\n guard !contentView.frame.contains(point) else { return false }\n return true\n default:\n return true\n }\n }\n\n func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UIPanGestureRecognizer:\n return tableView",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 425,
"end": 440,
"startLoc": {
"line": 425,
"column": 21,
"position": 3535
},
"endLoc": {
"line": 440,
"column": 10,
"position": 3683
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 583,
"end": 598,
"startLoc": {
"line": 583,
"column": 21,
"position": 4539
},
"endLoc": {
"line": 598,
"column": 24,
"position": 4687
}
}
},
{
"format": "swift",
"lines": 40,
"fragment": "else { return nil }\n return vc.backdropView\n }\n\n override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {\n super.init(presentedViewController: presentedViewController, presenting: presentingViewController)\n backdropView?.backgroundColor = Theme.backdropColor\n }\n\n override func presentationTransitionWillBegin() {\n guard let containerView = containerView, let backdropView = backdropView else { return }\n backdropView.alpha = 0\n containerView.addSubview(backdropView)\n backdropView.autoPinEdgesToSuperviewEdges()\n containerView.layoutIfNeeded()\n\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 1\n }, completion: nil)\n }\n\n override func dismissalTransitionWillBegin() {\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 0\n }, completion: { _ in\n self.backdropView?.removeFromSuperview()\n })\n }\n\n override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n guard let presentedView = presentedView else { return }\n coordinator.animate(alongsideTransition: { _ in\n presentedView.frame = self.frameOfPresentedViewInContainerView\n presentedView.layoutIfNeeded()\n }, completion: nil)\n }\n}\n\nextension GroupCallMemberSheet",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 452,
"end": 491,
"startLoc": {
"line": 452,
"column": 2,
"position": 3751
},
"endLoc": {
"line": 491,
"column": 21,
"position": 4123
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 610,
"end": 649,
"startLoc": {
"line": 610,
"column": 2,
"position": 4755
},
"endLoc": {
"line": 649,
"column": 21,
"position": 5127
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "()\n\n override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n backgroundColor = .clear\n selectionStyle = .none\n\n layoutMargins = UIEdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)\n\n contentView.addSubview(avatarView)\n avatarView.autoPinLeadingToSuperviewMargin()\n avatarView.autoPinHeightToSuperviewMargins()\n avatarView.autoSetDimensions(to: CGSize(square: avatarDiameter))\n\n nameLabel",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 534,
"end": 549,
"startLoc": {
"line": 534,
"column": 12,
"position": 4434
},
"endLoc": {
"line": 549,
"column": 10,
"position": 4568
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/EmojiReactorsTableView.swift",
"start": 78,
"end": 93,
"startLoc": {
"line": 78,
"column": 8,
"position": 610
},
"endLoc": {
"line": 93,
"column": 12,
"position": 744
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": "override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n backgroundColor = .clear\n selectionStyle = .none\n\n layoutMargins = UIEdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)\n\n let",
"tokens": 0,
"firstFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 601,
"end": 609,
"startLoc": {
"line": 601,
"column": 5,
"position": 5035
},
"endLoc": {
"line": 609,
"column": 4,
"position": 5124
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/EmojiReactorsTableView.swift",
"start": 80,
"end": 88,
"startLoc": {
"line": 80,
"column": 5,
"position": 615
},
"endLoc": {
"line": 88,
"column": 12,
"position": 704
}
}
},
{
"format": "swift",
"lines": 26,
"fragment": ", nameComponents.count == 2 else {\n return owsFailDebug(\"Received incorrectly formatted resourceName: \\(resourceName)\")\n }\n\n guard !receivedFileIds.contains(fileIdentifier) else {\n return Logger.info(\"Ignoring duplicate file: \\(fileIdentifier)\")\n }\n\n guard !skippedFileIds.contains(fileIdentifier) else {\n return Logger.info(\"Ignoring previously skipped file: \\(fileIdentifier)\")\n }\n\n guard let file: DeviceTransferProtoFile = {\n switch fileIdentifier {\n case DeviceTransferService.databaseIdentifier:\n return manifest.database?.database\n case DeviceTransferService.databaseWALIdentifier:\n return manifest.database?.wal\n default:\n return manifest.files.first(where: { $0.identifier == fileIdentifier })\n }\n }() else {\n return owsFailDebug(\"Received unexpected file on new device: \\(fileIdentifier)\")\n }\n\n if",
"tokens": 0,
"firstFile": {
"name": "util/Device Transfer/DeviceTransferService+MultipeerDelegates.swift",
"start": 240,
"end": 265,
"startLoc": {
"line": 240,
"column": 5,
"position": 1977
},
"endLoc": {
"line": 265,
"column": 3,
"position": 2189
}
},
"secondFile": {
"name": "util/Device Transfer/DeviceTransferService+MultipeerDelegates.swift",
"start": 181,
"end": 206,
"startLoc": {
"line": 181,
"column": 6,
"position": 1426
},
"endLoc": {
"line": 206,
"column": 7,
"position": 1638
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "let thread: TSThread?\n public init(thread: TSThread? = nil) {\n self.thread = thread\n super.init()\n\n NotificationCenter.default.addObserver(\n self,\n selector: #selector(updateTableContents),\n name: Wallpaper.wallpaperDidChangeNotification,\n object: nil\n )\n }\n\n public override func viewDidLoad() {\n super.viewDidLoad()\n\n title = NSLocalizedString(\"SET_WALLPAPER_TITLE\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Wallpapers/SetWallpaperViewController.swift",
"start": 18,
"end": 34,
"startLoc": {
"line": 18,
"column": 5,
"position": 130
},
"endLoc": {
"line": 34,
"column": 22,
"position": 246
}
},
"secondFile": {
"name": "ViewControllers/Wallpapers/WallpaperSettingsViewController.swift",
"start": 8,
"end": 24,
"startLoc": {
"line": 8,
"column": 5,
"position": 24
},
"endLoc": {
"line": 24,
"column": 27,
"position": 140
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "(address: SignalServiceAddress) -> Promise<Void> {\n guard let oldGroupModel = delegate?.currentGroupModel as? TSGroupModelV2 else {\n return Promise(error: OWSAssertionError(\"Missing group model.\"))\n }\n guard oldGroupModel.groupMembership.isMemberOfAnyKind(address) else {\n return Promise(error: OWSAssertionError(\"Not a group member.\"))\n }\n guard let uuid = address.uuid else {\n return Promise(error: OWSAssertionError(\"Invalid member address.\"))\n }\n return firstly {\n return GroupManager.messageProcessingPromise(for: oldGroupModel,\n description: \"Revoke group admin\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 119,
"end": 131,
"startLoc": {
"line": 119,
"column": 24,
"position": 994
},
"endLoc": {
"line": 131,
"column": 21,
"position": 1142
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 72,
"end": 84,
"startLoc": {
"line": 72,
"column": 22,
"position": 545
},
"endLoc": {
"line": 84,
"column": 19,
"position": 693
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "(address: SignalServiceAddress) -> Bool {\n guard let groupThread = thread as? TSGroupThread,\n groupThread.isGroupV2Thread else {\n return false\n }\n guard let localAddress = tsAccountManager.localAddress else {\n owsFailDebug(\"Missing localAddress.\")\n return false\n }\n // Only admins can kick out other members.\n let groupMembership = groupThread.groupModel.groupMembership\n let isLocalUserAdmin = groupMembership.isFullMemberAndAdministrator(localAddress)\n let isAddressInGroup",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 140,
"end": 152,
"startLoc": {
"line": 140,
"column": 19,
"position": 1207
},
"endLoc": {
"line": 152,
"column": 17,
"position": 1319
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 92,
"end": 103,
"startLoc": {
"line": 92,
"column": 37,
"position": 755
},
"endLoc": {
"line": 103,
"column": 15,
"position": 864
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "(address: SignalServiceAddress) -> Promise<Void> {\n guard let oldGroupModel = delegate?.currentGroupModel as? TSGroupModelV2 else {\n return Promise(error: OWSAssertionError(\"Missing group model.\"))\n }\n guard oldGroupModel.groupMembership.isMemberOfAnyKind(address) else {\n return Promise(error: OWSAssertionError(\"Not a group member.\"))\n }\n guard let uuid = address.uuid else {\n return Promise(error: OWSAssertionError(\"Invalid member address.\"))\n }\n return firstly {\n return GroupManager.messageProcessingPromise(for: oldGroupModel,\n description: \"Remove user from group\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 169,
"end": 181,
"startLoc": {
"line": 169,
"column": 23,
"position": 1463
},
"endLoc": {
"line": 181,
"column": 25,
"position": 1611
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupViewHelper+MemberActionSheet.swift",
"start": 72,
"end": 84,
"startLoc": {
"line": 72,
"column": 22,
"position": 545
},
"endLoc": {
"line": 84,
"column": 19,
"position": 693
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ") -> Promise<TSGroupThread> {\n guard let groupModelV2 = groupModel as? TSGroupModelV2 else {\n return Promise(error: OWSAssertionError(\"Invalid group model.\"))\n }\n let uuids = addresses.compactMap { $0.uuid }\n guard !uuids.isEmpty else {\n return Promise(error: OWSAssertionError(\"Invalid addresses.\"))\n }\n\n return firstly { () -> Promise<Void> in\n return GroupManager.messageProcessingPromise(for: groupModel,\n description: self.logTag)\n }.then(on: .global()) { _ in\n GroupManager.acceptOrDenyMemberRequestsV2",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupMemberRequestsAndInvitesViewController.swift",
"start": 583,
"end": 596,
"startLoc": {
"line": 583,
"column": 5,
"position": 4872
},
"endLoc": {
"line": 596,
"column": 29,
"position": 5036
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupMemberRequestsAndInvitesViewController.swift",
"start": 483,
"end": 496,
"startLoc": {
"line": 483,
"column": 2,
"position": 3951
},
"endLoc": {
"line": 496,
"column": 32,
"position": 4115
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "let cameraImageContainer = UIView()\n cameraImageContainer.autoSetDimensions(to: CGSize.square(32))\n cameraImageContainer.backgroundColor = Theme.isDarkThemeEnabled ? .ows_gray15 : UIColor(rgbHex: 0xf8f9f9)\n cameraImageContainer.layer.cornerRadius = 16\n\n cameraImageContainer.layer.shadowColor = UIColor.black.cgColor\n cameraImageContainer.layer.shadowOpacity = 0.2\n cameraImageContainer.layer.shadowRadius = 4\n cameraImageContainer.layer.shadowOffset = CGSize(width: 0, height: 2)\n\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupAttributesEditorHelper.swift",
"start": 127,
"end": 137,
"startLoc": {
"line": 127,
"column": 9,
"position": 807
},
"endLoc": {
"line": 137,
"column": 4,
"position": 933
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileSettingsViewController.swift",
"start": 244,
"end": 254,
"startLoc": {
"line": 244,
"column": 9,
"position": 1949
},
"endLoc": {
"line": 254,
"column": 5,
"position": 2075
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": ")\n\n let secondaryShadowView = UIView()\n secondaryShadowView.layer.shadowColor = UIColor.black.cgColor\n secondaryShadowView.layer.shadowOpacity = 0.12\n secondaryShadowView.layer.shadowRadius = 16\n secondaryShadowView.layer.shadowOffset = CGSize(width: 0, height: 4)\n\n cameraImageContainer.addSubview(secondaryShadowView)\n secondaryShadowView.autoPinEdgesToSuperviewEdges()\n\n let cameraImageView = UIImageView.withTemplateImageName(\"camera-outline-32\", tintColor: Theme.isDarkThemeEnabled ? .ows_gray80 : .ows_black)\n cameraImageView.autoSetDimensions(to: CGSize.square(20))\n cameraImageView.contentMode = .scaleAspectFit\n\n cameraImageContainer.addSubview(cameraImageView)\n cameraImageView.autoCenterInSuperview()\n\n return cameraImageContainer",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/GroupAttributesEditorHelper.swift",
"start": 135,
"end": 153,
"startLoc": {
"line": 135,
"column": 2,
"position": 929
},
"endLoc": {
"line": 153,
"column": 21,
"position": 1098
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileSettingsViewController.swift",
"start": 256,
"end": 274,
"startLoc": {
"line": 256,
"column": 16,
"position": 2115
},
"endLoc": {
"line": 274,
"column": 5,
"position": 2284
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": ")\n section.add(OWSTableItem(customCellBlock: { [weak self] in\n guard let self = self else {\n owsFailDebug(\"Missing self\")\n return OWSTableItem.newCell()\n }\n let cell = OWSTableItem.newCell()\n cell.preservesSuperviewLayoutMargins = true\n cell.contentView.preservesSuperviewLayoutMargins = true\n cell.selectionStyle = .none\n\n let iconView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 300,
"end": 311,
"startLoc": {
"line": 300,
"column": 24,
"position": 2455
},
"endLoc": {
"line": 311,
"column": 9,
"position": 2557
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 258,
"end": 269,
"startLoc": {
"line": 258,
"column": 41,
"position": 2044
},
"endLoc": {
"line": 269,
"column": 5,
"position": 2146
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "section.add(OWSTableItem(customCellBlock: { [weak self] in\n guard let self = self else {\n owsFailDebug(\"Missing self\")\n return OWSTableItem.newCell()\n }\n let cell = OWSTableItem.newCell()\n cell.preservesSuperviewLayoutMargins = true\n cell.contentView.preservesSuperviewLayoutMargins = true\n\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 620,
"end": 629,
"startLoc": {
"line": 620,
"column": 13,
"position": 5316
},
"endLoc": {
"line": 629,
"column": 4,
"position": 5403
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 259,
"end": 267,
"startLoc": {
"line": 259,
"column": 9,
"position": 2047
},
"endLoc": {
"line": 267,
"column": 5,
"position": 2133
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "{\n section.add(OWSTableItem(customCellBlock: { [weak self] in\n guard let self = self else {\n owsFailDebug(\"Missing self\")\n return OWSTableItem.newCell()\n }\n let cell = OWSTableItem.newCell()\n cell.preservesSuperviewLayoutMargins = true\n cell.contentView.preservesSuperviewLayoutMargins = true\n\n let iconView = OWSTableItem.buildIconInCircleView(icon: .settingsShowAllMembers",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 759,
"end": 769,
"startLoc": {
"line": 759,
"column": 2,
"position": 6572
},
"endLoc": {
"line": 769,
"column": 23,
"position": 6676
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 619,
"end": 629,
"startLoc": {
"line": 619,
"column": 2,
"position": 5313
},
"endLoc": {
"line": 629,
"column": 19,
"position": 5417
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": ")\n rowLabel.textColor = Theme.primaryTextColor\n rowLabel.font = OWSTableItem.primaryLabelFont\n rowLabel.lineBreakMode = .byTruncatingTail\n\n let contentRow = UIStackView(arrangedSubviews: [ iconView, rowLabel ])\n contentRow.spacing = self.iconSpacingSmall\n\n cell.contentView.addSubview(contentRow)\n contentRow.autoPinWidthToSuperviewMargins()\n contentRow.autoPinHeightToSuperview(withMargin: 7)\n\n return cell\n }) { [weak self] in\n self?.showAllGroupMembers",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 776,
"end": 790,
"startLoc": {
"line": 776,
"column": 69,
"position": 6731
},
"endLoc": {
"line": 790,
"column": 20,
"position": 6852
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+Contents.swift",
"start": 636,
"end": 650,
"startLoc": {
"line": 636,
"column": 64,
"position": 5472
},
"endLoc": {
"line": 650,
"column": 19,
"position": 5593
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": ".localAddress else {\n return Promise(error: OWSAssertionError(\"Missing localAddress.\"))\n }\n\n return firstly { () -> Promise<Void> in\n return GroupManager.messageProcessingPromise(for: oldGroupModel,\n description: self.logTag)\n }.then(on: .global()) { _ in\n // dmConfiguration: nil means don't change disappearing messages configuration.\n GroupManager.localUpdateExistingGroup(oldGroupModel: oldGroupModel,\n newGroupModel: newGroupModel,\n dmConfiguration: nil,\n groupUpdateSourceAddress: localAddress)\n }.asVoid()\n }\n\n // MARK: -\n\n private",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/AddToGroupViewController.swift",
"start": 246,
"end": 264,
"startLoc": {
"line": 246,
"column": 17,
"position": 2119
},
"endLoc": {
"line": 264,
"column": 8,
"position": 2257
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupAttributesViewController.swift",
"start": 298,
"end": 313,
"startLoc": {
"line": 298,
"column": 17,
"position": 2223
},
"endLoc": {
"line": 313,
"column": 2,
"position": 2355
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "hasUnsavedChanges {\n navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString(\"EDIT_GROUP_UPDATE_BUTTON\",\n comment: \"The title for the 'update group' button.\"),\n style: .plain,\n target: self,\n action: #selector(updateGroupPressed),\n accessibilityIdentifier: UIView.accessibilityIdentifier(in: self, name: \"update\"))\n } else {\n navigationItem.rightBarButtonItem = nil\n }\n }\n\n @objc func updateGroupPressed() {\n showConfirmationAlert",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/AddGroupMembersViewController.swift",
"start": 46,
"end": 59,
"startLoc": {
"line": 46,
"column": 2,
"position": 224
},
"endLoc": {
"line": 59,
"column": 22,
"position": 335
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupAttributesViewController.swift",
"start": 142,
"end": 155,
"startLoc": {
"line": 142,
"column": 2,
"position": 1060
},
"endLoc": {
"line": 155,
"column": 28,
"position": 1171
}
}
},
{
"format": "swift",
"lines": 38,
"fragment": ") else {\n let error = OWSAssertionError(\"Couldn't build group model.\")\n GroupViewUtils.showUpdateErrorUI(error: error)\n return\n }\n GroupViewUtils.updateGroupWithActivityIndicator(fromViewController: self,\n updatePromiseBlock: {\n self.updateGroupThreadPromise(newGroupModel: newGroupModel)\n },\n completion: { _ in\n dismissAndUpdateDelegate()\n })\n }\n\n func updateGroupThreadPromise(newGroupModel: TSGroupModel) -> Promise<Void> {\n\n let oldGroupModel = self.oldGroupModel\n\n guard let localAddress = tsAccountManager.localAddress else {\n return Promise(error: OWSAssertionError(\"Missing localAddress.\"))\n }\n\n return firstly { () -> Promise<Void> in\n return GroupManager.messageProcessingPromise(for: oldGroupModel,\n description: self.logTag)\n }.then(on: .global()) { _ in\n // dmConfiguration: nil means don't change disappearing messages configuration.\n GroupManager.localUpdateExistingGroup(oldGroupModel: oldGroupModel,\n newGroupModel: newGroupModel,\n dmConfiguration: nil,\n groupUpdateSourceAddress: localAddress)\n }.asVoid()\n }\n}\n\n// MARK: -\n\nextension AddGroupMembersViewController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ThreadSettings/AddGroupMembersViewController.swift",
"start": 152,
"end": 189,
"startLoc": {
"line": 152,
"column": 2,
"position": 1073
},
"endLoc": {
"line": 189,
"column": 30,
"position": 1347
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/GroupAttributesViewController.swift",
"start": 280,
"end": 317,
"startLoc": {
"line": 280,
"column": 14,
"position": 2089
},
"endLoc": {
"line": 317,
"column": 30,
"position": 2363
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "let messageBody = MessageBody(text: packUrl, ranges: .empty)\n let unapprovedContent = SendMessageUnapprovedContent.text(messageBody: messageBody)\n let sendMessageFlow = SendMessageFlow(flowType: .`default`,\n unapprovedContent: unapprovedContent,\n useConversationComposeForSingleRecipient: true,\n navigationController: navigationController,\n delegate: self)\n // Retain the flow until it is complete.\n self.sendMessageFlow = sendMessageFlow\n }",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Stickers/ManageStickersViewController.swift",
"start": 506,
"end": 515,
"startLoc": {
"line": 506,
"column": 9,
"position": 4329
},
"endLoc": {
"line": 515,
"column": 2,
"position": 4426
}
},
"secondFile": {
"name": "ViewControllers/Stickers/StickerPackViewController.swift",
"start": 398,
"end": 408,
"startLoc": {
"line": 398,
"column": 9,
"position": 3165
},
"endLoc": {
"line": 408,
"column": 8,
"position": 3263
}
}
},
{
"format": "swift",
"lines": 8,
"fragment": ")\n explanationLabel.textColor = Theme.accentBlueColor\n explanationLabel.font = UIFont.ows_dynamicTypeSubheadlineClamped\n explanationLabel.numberOfLines = 0\n explanationLabel.textAlignment = .center\n explanationLabel.lineBreakMode = .byWordWrapping\n explanationLabel.isUserInteractionEnabled = true\n explanationLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(explanationLabelTapped",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Registration/OnboardingSplashViewController.swift",
"start": 57,
"end": 64,
"startLoc": {
"line": 57,
"column": 74,
"position": 452
},
"endLoc": {
"line": 64,
"column": 23,
"position": 533
}
},
"secondFile": {
"name": "ViewControllers/Registration/SecondaryLinking/SecondaryLinkingQRCodeViewController.swift",
"start": 43,
"end": 50,
"startLoc": {
"line": 43,
"column": 79,
"position": 298
},
"endLoc": {
"line": 50,
"column": 23,
"position": 379
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": "{\n OWSActionSheets.showErrorAlert(message: NSLocalizedString(\"PROFILE_VIEW_ERROR_GIVEN_NAME_REQUIRED\",\n comment: \"Error message shown when user tries to update profile without a given name\"))\n return\n }\n\n if profileManager.isProfileNameTooLong(normalizedGivenName) {\n OWSActionSheets.showErrorAlert(message: NSLocalizedString(\"PROFILE_VIEW_ERROR_GIVEN_NAME_TOO_LONG\",\n comment: \"Error message shown when user tries to update profile with a given name that is too long.\"))\n return\n }\n\n if profileManager.isProfileNameTooLong(normalizedFamilyName) {\n OWSActionSheets.showErrorAlert(message: NSLocalizedString(\"PROFILE_VIEW_ERROR_FAMILY_NAME_TOO_LONG\",\n comment: \"Error message shown when user tries to update profile with a family name that is too long.\"))\n return\n }\n\n if",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Registration/OnboardingProfileCreationViewController.swift",
"start": 312,
"end": 330,
"startLoc": {
"line": 312,
"column": 2,
"position": 2781
},
"endLoc": {
"line": 330,
"column": 3,
"position": 2892
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileNameViewController.swift",
"start": 194,
"end": 218,
"startLoc": {
"line": 194,
"column": 2,
"position": 1293
},
"endLoc": {
"line": 218,
"column": 16,
"position": 1416
}
}
},
{
"format": "swift",
"lines": 32,
"fragment": ": AvatarViewHelperDelegate {\n\n public func avatarActionSheetTitle() -> String? {\n NSLocalizedString(\"PROFILE_VIEW_AVATAR_ACTIONSHEET_TITLE\", comment: \"Action Sheet title prompting the user for a profile avatar\")\n }\n\n public func avatarDidChange(_ image: UIImage) {\n AssertIsOnMainThread()\n\n setAvatarImage(image.resizedImage(toFillPixelSize: .square(CGFloat(kOWSProfileManager_MaxAvatarDiameter))))\n }\n\n public func fromViewController() -> UIViewController {\n self\n }\n\n public func hasClearAvatarAction() -> Bool {\n avatarData != nil\n }\n\n public func clearAvatar() {\n setAvatarImage(nil)\n }\n\n public func clearAvatarActionLabel() -> String {\n return NSLocalizedString(\"PROFILE_VIEW_CLEAR_AVATAR\", comment: \"Label for action that clear's the user's profile avatar\")\n }\n}\n\n// MARK: - <UITextFieldDelegate>\n\nextension OnboardingProfileCreationViewController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Registration/OnboardingProfileCreationViewController.swift",
"start": 398,
"end": 429,
"startLoc": {
"line": 398,
"column": 40,
"position": 3376
},
"endLoc": {
"line": 429,
"column": 40,
"position": 3576
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileSettingsViewController.swift",
"start": 291,
"end": 321,
"startLoc": {
"line": 291,
"column": 30,
"position": 2395
},
"endLoc": {
"line": 321,
"column": 30,
"position": 2593
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": "progressView.stopAnimatingImmediately()\n progressView.removeFromSuperview()\n\n self.nextButton.alpha = 1\n self.pinTypeToggle.alpha = 1\n self.pinTextField.alpha = 1\n self.validationWarningLabel.alpha = 1\n self.needHelpLink.alpha = 1\n self.view.isUserInteractionEnabled = true\n\n // If we have success while pending restoration, show the next onboarding milestone.\n if",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Registration/Onboarding2FAViewController.swift",
"start": 320,
"end": 331,
"startLoc": {
"line": 320,
"column": 17,
"position": 2476
},
"endLoc": {
"line": 331,
"column": 3,
"position": 2561
}
},
"secondFile": {
"name": "ViewControllers/Registration/Onboarding2FAViewController.swift",
"start": 305,
"end": 314,
"startLoc": {
"line": 305,
"column": 17,
"position": 2366
},
"endLoc": {
"line": 314,
"column": 5,
"position": 2447
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": "recipientPicker.delegate = self\n addChild(recipientPicker)\n view.addSubview(recipientPicker.view)\n recipientPicker.view.autoPin(toTopLayoutGuideOf: self, withInset: 0)\n recipientPicker.view.autoPinEdge(toSuperviewEdge: .leading)\n recipientPicker.view.autoPinEdge(toSuperviewEdge: .trailing)\n recipientPicker.view.autoPinEdge(toSuperviewEdge: .bottom)\n\n recipientPicker",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/RecipientPicker/AddToBlockListViewController.swift",
"start": 24,
"end": 32,
"startLoc": {
"line": 24,
"column": 9,
"position": 111
},
"endLoc": {
"line": 32,
"column": 16,
"position": 198
}
},
"secondFile": {
"name": "ViewControllers/RecipientPicker/ComposeViewController.swift",
"start": 23,
"end": 31,
"startLoc": {
"line": 23,
"column": 9,
"position": 124
},
"endLoc": {
"line": 31,
"column": 15,
"position": 211
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ")\n }\n\n override func viewWillAppear(_ animated: Bool) {\n super.viewWillAppear(animated)\n recipientPicker.applyTheme(to: self)\n }\n\n override func viewWillDisappear(_ animated: Bool) {\n super.viewWillDisappear(animated)\n recipientPicker.removeTheme(from: self)\n }\n\n func",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/RecipientPicker/AddToBlockListViewController.swift",
"start": 35,
"end": 48,
"startLoc": {
"line": 35,
"column": 9,
"position": 218
},
"endLoc": {
"line": 48,
"column": 5,
"position": 305
}
},
"secondFile": {
"name": "ViewControllers/RecipientPicker/ComposeViewController.swift",
"start": 31,
"end": 44,
"startLoc": {
"line": 31,
"column": 2,
"position": 240
},
"endLoc": {
"line": 44,
"column": 6,
"position": 327
}
}
},
{
"format": "swift",
"lines": 23,
"fragment": "(thread: groupThread)\n }\n }\n\n func recipientPicker(_ recipientPickerViewController: RecipientPickerViewController,\n willRenderRecipient recipient: PickedRecipient) {\n // Do nothing.\n }\n\n func recipientPicker(_ recipientPickerViewController: RecipientPickerViewController,\n prepareToSelectRecipient recipient: PickedRecipient) -> AnyPromise {\n owsFailDebug(\"This method should not called.\")\n return AnyPromise(Promise.value(()))\n }\n\n func recipientPicker(_ recipientPickerViewController: RecipientPickerViewController,\n showInvalidRecipientAlert recipient: PickedRecipient) {\n owsFailDebug(\"Unexpected error.\")\n }\n\n func recipientPicker(\n _ recipientPickerViewController: RecipientPickerViewController,\n accessoryMessageForRecipient",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/RecipientPicker/AddToBlockListViewController.swift",
"start": 99,
"end": 121,
"startLoc": {
"line": 99,
"column": 6,
"position": 681
},
"endLoc": {
"line": 121,
"column": 29,
"position": 829
}
},
"secondFile": {
"name": "ViewControllers/RecipientPicker/ComposeViewController.swift",
"start": 85,
"end": 107,
"startLoc": {
"line": 85,
"column": 16,
"position": 635
},
"endLoc": {
"line": 107,
"column": 21,
"position": 783
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "}\n\n func recipientPicker(\n _ recipientPickerViewController: RecipientPickerViewController,\n accessoryMessageForRecipient recipient: PickedRecipient\n ) -> String? {\n switch recipient.identifier {\n case .address(let address):\n guard contactsViewHelper.isSignalServiceAddressBlocked(address) else { return nil }\n return MessageStrings.conversationIsBlocked\n case .group(let thread):\n guard contactsViewHelper.isThreadBlocked(thread) else { return nil }\n return MessageStrings.conversationIsBlocked\n }\n }\n\n func recipientPickerTableViewWillBeginDragging",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/RecipientPicker/AddToBlockListViewController.swift",
"start": 117,
"end": 133,
"startLoc": {
"line": 117,
"column": 5,
"position": 810
},
"endLoc": {
"line": 133,
"column": 42,
"position": 944
}
},
"secondFile": {
"name": "ViewControllers/RecipientPicker/ComposeViewController.swift",
"start": 108,
"end": 124,
"startLoc": {
"line": 108,
"column": 2,
"position": 794
},
"endLoc": {
"line": 124,
"column": 16,
"position": 928
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": ",\n diameter: UInt(UIScreen.main.bounds.size.smallerAxis),\n transaction: readTx) else { return nil }\n\n self.avatarImage = avatarImage\n super.init(nibName: nil, bundle: nil)\n\n modalPresentationStyle = .custom\n transitioningDelegate = self\n }\n\n override",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Photos/AvatarViewController.swift",
"start": 48,
"end": 59,
"startLoc": {
"line": 48,
"column": 8,
"position": 375
},
"endLoc": {
"line": 59,
"column": 9,
"position": 460
}
},
"secondFile": {
"name": "ViewControllers/Photos/AvatarViewController.swift",
"start": 34,
"end": 45,
"startLoc": {
"line": 34,
"column": 7,
"position": 251
},
"endLoc": {
"line": 45,
"column": 6,
"position": 336
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": ")\n\n let buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_semibold\n let buttonHeight = OWSFlatButton.heightForFont(buttonFont)\n let okayButton = OWSFlatButton.button(title: CommonStrings.okayButton,\n font: buttonFont,\n titleColor: .white,\n backgroundColor: .ows_accentBlue,\n target: self,\n selector: #selector(dismissAlert))\n okayButton.autoSetDimension(.height, toSize: buttonHeight)\n\n let stackView = UIStackView(arrangedSubviews: [\n wrapViewWithHMargins",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/NewGroupView/NewGroupConfirmViewController.swift",
"start": 522,
"end": 535,
"startLoc": {
"line": 522,
"column": 4,
"position": 4011
},
"endLoc": {
"line": 535,
"column": 21,
"position": 4132
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+LegacyGroups.swift",
"start": 206,
"end": 219,
"startLoc": {
"line": 206,
"column": 68,
"position": 1530
},
"endLoc": {
"line": 219,
"column": 11,
"position": 1651
}
}
},
{
"format": "swift",
"lines": 18,
"fragment": ")\n\n layoutMargins = .zero\n addSubview(stackView)\n stackView.autoPinEdgesToSuperviewMargins()\n\n let actionSheetController = ActionSheetController()\n actionSheetController.customHeader = self\n actionSheetController.isCancelable = true\n fromViewController.presentActionSheet(actionSheetController)\n self.actionSheetController = actionSheetController\n }\n\n @objc\n func dismissAlert() {\n actionSheetController?.dismiss(animated: true)\n }\n}",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/NewGroupView/NewGroupConfirmViewController.swift",
"start": 545,
"end": 562,
"startLoc": {
"line": 545,
"column": 21,
"position": 4251
},
"endLoc": {
"line": 562,
"column": 2,
"position": 4353
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/ConversationSettingsViewController+LegacyGroups.swift",
"start": 237,
"end": 256,
"startLoc": {
"line": 237,
"column": 16,
"position": 1826
},
"endLoc": {
"line": 256,
"column": 2,
"position": 1932
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "indexPath: IndexPath) -> Bool {\n\n Logger.debug(\"\")\n\n guard galleryDates.count > 0 else {\n return false\n }\n\n switch indexPath.section {\n case kLoadOlderSectionIdx, loadNewerSectionIdx:\n return false\n default:\n return true\n }\n }\n\n override public func collectionView(_ collectionView: UICollectionView, didSelectItemAt",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MediaGallery/MediaTileViewController.swift",
"start": 203,
"end": 219,
"startLoc": {
"line": 203,
"column": 2,
"position": 1649
},
"endLoc": {
"line": 219,
"column": 16,
"position": 1752
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/MediaTileViewController.swift",
"start": 171,
"end": 187,
"startLoc": {
"line": 171,
"column": 2,
"position": 1439
},
"endLoc": {
"line": 187,
"column": 21,
"position": 1542
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": "guard let collectionView = self.collectionView else {\n owsFailDebug(\"collectionView was unexpectedly nil\")\n return\n }\n\n // hide toolbar\n UIView.animate(withDuration: 0.1, delay: 0, options: .curveEaseInOut, animations: {\n NSLayoutConstraint.deactivate([self.footerBarBottomConstraint])\n self.footerBarBottomConstraint = self.footerBar.autoPinEdge",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MediaGallery/MediaTileViewController.swift",
"start": 561,
"end": 569,
"startLoc": {
"line": 561,
"column": 9,
"position": 4570
},
"endLoc": {
"line": 569,
"column": 12,
"position": 4654
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/MediaTileViewController.swift",
"start": 529,
"end": 537,
"startLoc": {
"line": 529,
"column": 9,
"position": 4349
},
"endLoc": {
"line": 537,
"column": 8,
"position": 4433
}
}
},
{
"format": "swift",
"lines": 40,
"fragment": ": UICollectionViewLayoutAttributes]()\n\n private var contentSize = CGSize.zero\n\n // MARK: Initializers and Factory Methods\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n required init?(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n override init() {\n super.init()\n }\n\n // MARK: Methods\n\n override func invalidateLayout() {\n super.invalidateLayout()\n\n itemAttributesMap.removeAll()\n }\n\n override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {\n super.invalidateLayout(with: context)\n\n itemAttributesMap.removeAll()\n }\n\n override func prepare() {\n super.prepare()\n\n guard let collectionView = collectionView else {\n return\n }\n guard let delegate = delegate else {\n return\n }\n\n let vInset =",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/GifPicker/GifPickerLayout.swift",
"start": 16,
"end": 55,
"startLoc": {
"line": 16,
"column": 5,
"position": 75
},
"endLoc": {
"line": 55,
"column": 2,
"position": 302
}
},
"secondFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoGridLayout.swift",
"start": 20,
"end": 55,
"startLoc": {
"line": 20,
"column": 4,
"position": 125
},
"endLoc": {
"line": 55,
"column": 2,
"position": 347
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "}\n\n override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {\n return itemAttributesMap.values.filter { itemAttributes in\n return itemAttributes.frame.intersects(rect)\n }\n }\n\n override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/GifPicker/GifPickerLayout.swift",
"start": 120,
"end": 129,
"startLoc": {
"line": 120,
"column": 5,
"position": 991
},
"endLoc": {
"line": 129,
"column": 4,
"position": 1077
}
},
"secondFile": {
"name": "Calls/UserInterface/Group/GroupCallVideoGridLayout.swift",
"start": 139,
"end": 148,
"startLoc": {
"line": 139,
"column": 5,
"position": 1283
},
"endLoc": {
"line": 148,
"column": 7,
"position": 1369
}
}
},
{
"format": "swift",
"lines": 23,
"fragment": ")\n topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)\n }\n\n override public func viewWillAppear(_ animated: Bool) {\n super.viewWillAppear(animated)\n\n progressView.startUpdatingProgress()\n\n deviceTransferService.addObserver(self)\n }\n\n public override func viewWillDisappear(_ animated: Bool) {\n super.viewWillDisappear(animated)\n\n progressView.stopUpdatingProgress()\n\n deviceTransferService.removeObserver(self)\n deviceTransferService.cancelTransferFromOldDevice()\n }\n\n @objc\n func didTapNext",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Device Transfer/DeviceTransferProgressViewController.swift",
"start": 45,
"end": 67,
"startLoc": {
"line": 45,
"column": 13,
"position": 293
},
"endLoc": {
"line": 67,
"column": 11,
"position": 430
}
},
"secondFile": {
"name": "ViewControllers/Registration/Device Transfer/OnboardingTransferProgressViewController.swift",
"start": 57,
"end": 82,
"startLoc": {
"line": 57,
"column": 2,
"position": 382
},
"endLoc": {
"line": 82,
"column": 13,
"position": 524
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "let actionSheet = ActionSheetController(\n title: NSLocalizedString(\"DEVICE_TRANSFER_CANCEL_CONFIRMATION_TITLE\",\n comment: \"The title of the dialog asking the user if they want to cancel a device transfer\"),\n message: NSLocalizedString(\"DEVICE_TRANSFER_CANCEL_CONFIRMATION_MESSAGE\",\n comment: \"The message of the dialog asking the user if they want to cancel a device transfer\")\n )\n actionSheet.addAction(OWSActionSheets.cancelAction)\n\n let okAction = ActionSheetAction(\n title: NSLocalizedString(\"DEVICE_TRANSFER_CANCEL_CONFIRMATION_ACTION\",\n comment: \"The stop action of the dialog asking the user if they want to cancel a device transfer\"),\n style: .destructive\n ) { _ in\n self.dismissActionSheet",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Device Transfer/DeviceTransferNavigationController.swift",
"start": 39,
"end": 52,
"startLoc": {
"line": 39,
"column": 13,
"position": 285
},
"endLoc": {
"line": 52,
"column": 19,
"position": 387
}
},
"secondFile": {
"name": "ViewControllers/Registration/Device Transfer/OnboardingTransferProgressViewController.swift",
"start": 89,
"end": 102,
"startLoc": {
"line": 89,
"column": 9,
"position": 567
},
"endLoc": {
"line": 102,
"column": 21,
"position": 669
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "self.databaseStorage.write { transaction in\n let oldDMConfig = oldGroupThread.disappearingMessagesConfiguration(with: transaction)\n _ = OWSDisappearingMessagesConfiguration.applyToken(oldDMConfig.asToken,\n toThread: newGroupThread,\n transaction: transaction)\n }\n\n Logger.info(\"Complete.\")\n\n SignalApp.shared().presentConversation(for: newGroupThread, animated: true)\n }.catch(on: .global()) { error in\n owsFailDebug(\"Error: \\(error)\")\n }\n }\n\n class func copyToAnotherGroup",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/DebugUI/DebugUIStress.swift",
"start": 123,
"end": 138,
"startLoc": {
"line": 123,
"column": 13,
"position": 1075
},
"endLoc": {
"line": 138,
"column": 19,
"position": 1208
}
},
"secondFile": {
"name": "ViewControllers/DebugUI/DebugUIStress.swift",
"start": 45,
"end": 62,
"startLoc": {
"line": 45,
"column": 13,
"position": 280
},
"endLoc": {
"line": 62,
"column": 15,
"position": 419
}
}
},
{
"format": "swift",
"lines": 8,
"fragment": ")\", style: .default) { _ in\n guard let textField = alert.textFields?.first else {\n owsFailDebug(\"missing text field\")\n return\n }\n\n guard let inputString = textField.text, inputString.count >= 4 else {\n OWSActionSheets.showActionSheet(title: \"new file dir missing or less than 4 chars\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/DebugUI/DebugUIFileBrowser.swift",
"start": 171,
"end": 178,
"startLoc": {
"line": 171,
"column": 9,
"position": 1538
},
"endLoc": {
"line": 178,
"column": 44,
"position": 1622
}
},
"secondFile": {
"name": "ViewControllers/DebugUI/DebugUIFileBrowser.swift",
"start": 126,
"end": 133,
"startLoc": {
"line": 126,
"column": 18,
"position": 1090
},
"endLoc": {
"line": 133,
"column": 45,
"position": 1174
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": ",\n message: \"Will be created in \\(strongSelf.fileURL.lastPathComponent)\",\n preferredStyle: .alert)\n\n alert.addAction(UIAlertAction(title: \"Cancel\", style: .cancel, handler: nil))\n alert.addAction(UIAlertAction(title: \"Create\", style: .default) { _ in\n guard let textField = alert.textFields?.first else {\n owsFailDebug(\"missing text field\")\n return\n }\n\n guard let inputString = textField.text, inputString.count >= 4 else {\n OWSActionSheets.showActionSheet(title: \"dir name missing or less than 4 chars\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/DebugUI/DebugUIFileBrowser.swift",
"start": 320,
"end": 332,
"startLoc": {
"line": 320,
"column": 14,
"position": 2962
},
"endLoc": {
"line": 332,
"column": 40,
"position": 3108
}
},
"secondFile": {
"name": "ViewControllers/DebugUI/DebugUIFileBrowser.swift",
"start": 282,
"end": 294,
"startLoc": {
"line": 282,
"column": 15,
"position": 2624
},
"endLoc": {
"line": 294,
"column": 41,
"position": 2770
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "}\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(dictionary dictionaryValue: [String: Any]!) throws {\n notImplemented()\n }\n\n @objc\n public let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/TypingIndicatorInteraction.swift",
"start": 20,
"end": 35,
"startLoc": {
"line": 20,
"column": 5,
"position": 104
},
"endLoc": {
"line": 35,
"column": 4,
"position": 209
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/UnreadIndicatorInteraction.swift",
"start": 18,
"end": 33,
"startLoc": {
"line": 18,
"column": 5,
"position": 88
},
"endLoc": {
"line": 33,
"column": 5,
"position": 193
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "}\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(dictionary dictionaryValue: [String: Any]!) throws {\n notImplemented()\n }\n\n @objc\n public init(thread: TSThread, timestamp: UInt64)",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/ThreadDetailsInteraction.swift",
"start": 18,
"end": 33,
"startLoc": {
"line": 18,
"column": 5,
"position": 88
},
"endLoc": {
"line": 33,
"column": 2,
"position": 205
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/UnreadIndicatorInteraction.swift",
"start": 18,
"end": 33,
"startLoc": {
"line": 18,
"column": 5,
"position": 88
},
"endLoc": {
"line": 33,
"column": 2,
"position": 205
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "{\n buttons = [\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_BLOCK_BUTTON\",\n comment: \"A button used to block a user on an incoming message request.\"),\n titleColor: .ows_accentRed) { [weak self] in\n self?.delegate?.messageRequestViewDidTapBlock(mode: mode)\n },\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_DELETE_BUTTON\",\n comment: \"incoming message request button text which deletes a conversation\"),\n titleColor: .ows_accentRed) { [weak self] in\n self?.delegate?.messageRequestViewDidTapDelete()\n },\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_ACCEPT_BUTTON\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/MessageRequestView.swift",
"start": 257,
"end": 269,
"startLoc": {
"line": 257,
"column": 2,
"position": 1743
},
"endLoc": {
"line": 269,
"column": 37,
"position": 1868
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/MessageRequestView.swift",
"start": 237,
"end": 249,
"startLoc": {
"line": 237,
"column": 2,
"position": 1555
},
"endLoc": {
"line": 249,
"column": 39,
"position": 1680
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "buttons = [\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_BLOCK_BUTTON\",\n comment: \"A button used to block a user on an incoming message request.\"),\n titleColor: .ows_accentRed) { [weak self] in\n self?.delegate?.messageRequestViewDidTapBlock(mode: mode)\n },\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_DELETE_BUTTON\",\n comment: \"incoming message request button text which deletes a conversation\"),\n titleColor: .ows_accentRed) { [weak self] in\n self?.delegate?.messageRequestViewDidTapDelete()\n },\n prepareButton(title: NSLocalizedString(\"MESSAGE_REQUEST_VIEW_ACCEPT_BUTTON\",\n comment: \"A button used to accept a user on an incoming message request.\"),\n titleColor: Theme.accentBlueColor) { [weak self] in\n self?.delegate?.messageRequestViewDidTapAccept(mode: mode)\n }]\n return",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/MessageRequestView.swift",
"start": 298,
"end": 314,
"startLoc": {
"line": 298,
"column": 2,
"position": 2063
},
"endLoc": {
"line": 314,
"column": 7,
"position": 2235
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/MessageRequestView.swift",
"start": 238,
"end": 274,
"startLoc": {
"line": 238,
"column": 13,
"position": 1558
},
"endLoc": {
"line": 274,
"column": 2,
"position": 1918
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": "}\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n @objc\n public required init(dictionary dictionaryValue: [String: Any]!) throws {\n notImplemented()\n }\n\n @objc\n public init(thread: TSThread, timestamp: UInt64) {\n // Include timestamp in uniqueId to ensure invariant that\n // interactions don't move in the chat history ordering.\n super.init(uniqueId: \"DateHeader_",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/DateHeaderInteraction.swift",
"start": 18,
"end": 36,
"startLoc": {
"line": 18,
"column": 5,
"position": 88
},
"endLoc": {
"line": 36,
"column": 13,
"position": 223
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/UnreadIndicatorInteraction.swift",
"start": 18,
"end": 36,
"startLoc": {
"line": 18,
"column": 5,
"position": 88
},
"endLoc": {
"line": 36,
"column": 16,
"position": 223
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": "var sortIdToIndexPathMap = [UInt64: IndexPath]()\n for (index, renderItem) in renderItems.enumerated() {\n let indexPath = IndexPath(row: index, section: Self.messageSection)\n let sortId = renderItem.interaction.sortId\n sortIdToIndexPathMap[sortId] = indexPath\n }\n\n // Honor the scroll continuity bias.\n //\n // If we prefer continuity with regard to the bottom\n // of the conversation, start with the last items.\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/ConversationViewController+Scroll.swift",
"start": 646,
"end": 657,
"startLoc": {
"line": 646,
"column": 9,
"position": 4495
},
"endLoc": {
"line": 657,
"column": 4,
"position": 4593
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/ConversationViewController+Scroll.swift",
"start": 588,
"end": 595,
"startLoc": {
"line": 588,
"column": 9,
"position": 3982
},
"endLoc": {
"line": 595,
"column": 4,
"position": 4068
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": "guard let self = self else {\n return\n }\n\n // If the scroll action is not animated, perform it _before_\n // updateViewToReflectLoad().\n if !scrollAction.isAnimated {\n self.perform(scrollAction: scrollAction)\n }\n\n self.updateViewToReflectLoad(loadedRenderState: renderState)\n\n self.loadDidLand()\n\n if scrollAction.isAnimated {\n self.perform(scrollAction: scrollAction)\n }\n\n viewState",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/ConversationViewController+CVC.swift",
"start": 567,
"end": 585,
"startLoc": {
"line": 567,
"column": 13,
"position": 3397
},
"endLoc": {
"line": 585,
"column": 10,
"position": 3494
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/ConversationViewController+CVC.swift",
"start": 424,
"end": 436,
"startLoc": {
"line": 424,
"column": 13,
"position": 2368
},
"endLoc": {
"line": 436,
"column": 2,
"position": 2459
}
}
},
{
"format": "swift",
"lines": 34,
"fragment": "?\n\n @objc\n init(threadViewModel: ThreadViewModel, fromViewController: UIViewController) {\n let thread = threadViewModel.threadRecord\n self.thread = thread\n owsAssertDebug(thread as? TSGroupThread != nil)\n self.fromViewController = fromViewController\n\n super.init(frame: .zero)\n\n createContents()\n }\n\n private func createContents() {\n // We want the background to extend to the bottom of the screen\n // behind the safe area, so we add that inset to our bottom inset\n // instead of pinning this view to the safe area\n let safeAreaInset = safeAreaInsets.bottom\n\n autoresizingMask = .flexibleHeight\n\n axis = .vertical\n spacing = 11\n layoutMargins = UIEdgeInsets(top: 16, leading: 16, bottom: 20 + safeAreaInset, trailing: 16)\n isLayoutMarginsRelativeArrangement = true\n alignment = .fill\n\n let backgroundView = UIView()\n backgroundView.backgroundColor = Theme.backgroundColor\n addSubview(backgroundView)\n backgroundView.autoPinEdgesToSuperviewEdges()\n\n let format",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ConversationView/BlockingGroupMigrationView.swift",
"start": 13,
"end": 46,
"startLoc": {
"line": 13,
"column": 17,
"position": 50
},
"endLoc": {
"line": 46,
"column": 7,
"position": 286
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/MemberRequestView.swift",
"start": 16,
"end": 49,
"startLoc": {
"line": 16,
"column": 23,
"position": 65
},
"endLoc": {
"line": 49,
"column": 6,
"position": 301
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "}\n\n private let collectionViewFlowLayout = UICollectionViewFlowLayout()\n\n init() {\n super.init(frame: .zero, collectionViewLayout: collectionViewFlowLayout)\n\n dataSource = self\n delegate = self\n showsHorizontalScrollIndicator = false\n\n contentInset = UIEdgeInsets(top: 0, leading: 6, bottom: 0, trailing: 6)\n\n backgroundColor = .clear\n\n register(AttachmentFormatCell",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/Attachment Keyboard/AttachmentFormatPickerView.swift",
"start": 24,
"end": 39,
"startLoc": {
"line": 24,
"column": 5,
"position": 130
},
"endLoc": {
"line": 39,
"column": 21,
"position": 239
}
},
"secondFile": {
"name": "ViewControllers/Attachment Keyboard/RecentPhotoCollectionView.swift",
"start": 64,
"end": 79,
"startLoc": {
"line": 64,
"column": 5,
"position": 466
},
"endLoc": {
"line": 79,
"column": 16,
"position": 575
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "nameForTheme(mode),\n actionBlock: { [weak self] in\n self?.changeTheme(mode)\n },\n accessoryType: Theme.getOrFetchCurrentTheme() == mode ? .checkmark : .none\n )\n }\n\n func changeTheme(_ mode: ThemeMode) {\n Theme.setCurrent(mode)\n updateTableContents()\n }\n\n var",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/AppearanceSettingsTableViewController.swift",
"start": 60,
"end": 73,
"startLoc": {
"line": 60,
"column": 2,
"position": 438
},
"endLoc": {
"line": 73,
"column": 4,
"position": 535
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/ThemeSettingsTableViewController.swift",
"start": 38,
"end": 51,
"startLoc": {
"line": 38,
"column": 2,
"position": 231
},
"endLoc": {
"line": 51,
"column": 7,
"position": 328
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "func nameForTheme(_ mode: ThemeMode) -> String {\n switch mode {\n case .dark:\n return NSLocalizedString(\"APPEARANCE_SETTINGS_DARK_THEME_NAME\", comment: \"Name indicating that the dark theme is enabled.\")\n case .light:\n return NSLocalizedString(\"APPEARANCE_SETTINGS_LIGHT_THEME_NAME\", comment: \"Name indicating that the light theme is enabled.\")\n case .system:\n return NSLocalizedString(\"APPEARANCE_SETTINGS_SYSTEM_THEME_NAME\", comment: \"Name indicating that the system theme is enabled.\")\n }\n }\n}",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/AppearanceSettingsTableViewController.swift",
"start": 77,
"end": 87,
"startLoc": {
"line": 77,
"column": 5,
"position": 561
},
"endLoc": {
"line": 87,
"column": 2,
"position": 656
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/ThemeSettingsTableViewController.swift",
"start": 55,
"end": 69,
"startLoc": {
"line": 55,
"column": 2,
"position": 358
},
"endLoc": {
"line": 69,
"column": 6,
"position": 458
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "avatarData {\n avatarImageView.image = UIImage(data: avatarData)\n } else {\n avatarImageView.image = OWSContactAvatarBuilder(forLocalUserWithDiameter: UInt(avatarDiameter)).buildDefaultImage()\n }\n avatarImageView.clipsToBounds = true\n avatarImageView.layer.cornerRadius = avatarDiameter / 2\n avatarImageView.autoSetDimensions(to: CGSize(square: avatarDiameter))\n\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/AppSettings/AppSettingsViewController.swift",
"start": 202,
"end": 211,
"startLoc": {
"line": 202,
"column": 2,
"position": 1860
},
"endLoc": {
"line": 211,
"column": 4,
"position": 1954
}
},
"secondFile": {
"name": "ViewControllers/AppSettings/Profile/ProfileSettingsViewController.swift",
"start": 231,
"end": 240,
"startLoc": {
"line": 231,
"column": 2,
"position": 1830
},
"endLoc": {
"line": 240,
"column": 5,
"position": 1924
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "}\n\n func titleLabel(text: String) -> UILabel {\n let titleLabel = UILabel()\n titleLabel.text = text\n titleLabel.textColor = Theme.primaryTextColor\n titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_semibold\n titleLabel.numberOfLines = 0\n titleLabel.lineBreakMode = .byWordWrapping\n titleLabel.textAlignment = .center\n titleLabel",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/NotificationPermissionReminderMegaphone.swift",
"start": 119,
"end": 129,
"startLoc": {
"line": 119,
"column": 5,
"position": 870
},
"endLoc": {
"line": 129,
"column": 11,
"position": 965
}
},
"secondFile": {
"name": "ViewControllers/Device Transfer/DeviceTransferNavigationController.swift",
"start": 99,
"end": 109,
"startLoc": {
"line": 99,
"column": 5,
"position": 721
},
"endLoc": {
"line": 109,
"column": 7,
"position": 816
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": "return titleLabel\n }\n\n func explanationLabel(explanationText: String) -> UILabel {\n let explanationLabel = UILabel()\n explanationLabel.textColor = Theme.secondaryTextAndIconColor\n explanationLabel.font = .ows_dynamicTypeBody2\n explanationLabel.text = explanationText\n explanationLabel.numberOfLines = 0\n explanationLabel.textAlignment = .center\n explanationLabel.lineBreakMode = .byWordWrapping\n explanationLabel",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/NotificationPermissionReminderMegaphone.swift",
"start": 131,
"end": 142,
"startLoc": {
"line": 131,
"column": 9,
"position": 979
},
"endLoc": {
"line": 142,
"column": 17,
"position": 1076
}
},
"secondFile": {
"name": "ViewControllers/Device Transfer/DeviceTransferNavigationController.swift",
"start": 109,
"end": 120,
"startLoc": {
"line": 109,
"column": 9,
"position": 816
},
"endLoc": {
"line": 120,
"column": 7,
"position": 913
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "return explanationLabel\n }\n\n func button(title: String, selector: Selector) -> OWSFlatButton {\n let font = UIFont.ows_dynamicTypeBodyClamped.ows_semibold\n let buttonHeight = OWSFlatButton.heightForFont(font)\n let button = OWSFlatButton.button(title: title,\n font: font,\n titleColor: .white,\n backgroundColor: .ows_accentBlue,\n target: self,\n selector: selector)\n button.autoSetDimension(.height, toSize: buttonHeight)\n return button\n }\n\n private",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/NotificationPermissionReminderMegaphone.swift",
"start": 144,
"end": 160,
"startLoc": {
"line": 144,
"column": 9,
"position": 1090
},
"endLoc": {
"line": 160,
"column": 8,
"position": 1228
}
},
"secondFile": {
"name": "ViewControllers/Device Transfer/DeviceTransferNavigationController.swift",
"start": 120,
"end": 135,
"startLoc": {
"line": 120,
"column": 9,
"position": 913
},
"endLoc": {
"line": 135,
"column": 2,
"position": 1049
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": ")\n navigationController?.setNavigationBarHidden(true, animated: false)\n }\n\n override func viewWillDisappear(_ animated: Bool) {\n super.viewWillDisappear(animated)\n navigationController?.setNavigationBarHidden(false, animated: false)\n }\n\n override func loadView() {\n\n self.view = UIView.container()\n self.view.backgroundColor = Theme.backgroundColor\n\n let title",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/GroupsV2AndMentionsSplash.swift",
"start": 22,
"end": 36,
"startLoc": {
"line": 22,
"column": 2,
"position": 133
},
"endLoc": {
"line": 36,
"column": 6,
"position": 240
}
},
"secondFile": {
"name": "Experience Upgrades/Upgrade Views/IntroducingPINs.swift",
"start": 65,
"end": 79,
"startLoc": {
"line": 65,
"column": 9,
"position": 515
},
"endLoc": {
"line": 79,
"column": 14,
"position": 622
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": ")\n }\n }\n\n private class func showLearnMoreView() {\n guard let url = URL(string: \"https://support.signal.org/hc/articles/360007319331\") else {\n owsFailDebug(\"Invalid url.\")\n return\n }\n guard let fromViewController = CurrentAppContext().frontmostViewController() else {\n owsFailDebug(\"Missing fromViewController.\")\n return\n }\n let vc = SFSafariViewController(url: url)\n fromViewController.present(vc, animated: true, completion: nil)\n }\n}",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/GroupsV2AndMentionsSplash.swift",
"start": 159,
"end": 175,
"startLoc": {
"line": 159,
"column": 2,
"position": 1337
},
"endLoc": {
"line": 175,
"column": 2,
"position": 1463
}
},
"secondFile": {
"name": "ViewControllers/NewGroupView/NewGroupConfirmViewController.swift",
"start": 391,
"end": 407,
"startLoc": {
"line": 391,
"column": 12,
"position": 2975
},
"endLoc": {
"line": 407,
"column": 2,
"position": 3101
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": ",\n comment: \"Snooze action text for contact permission reminder megaphone\")\n )\n setButtons(primary: primaryButton, secondary: secondaryButton)\n }\n\n required init(coder: NSCoder) {\n fatalError(\"init(coder:) has not been implemented\")\n }\n\n override func dismiss(animated: Bool = true, completion: (() -> Void)? = nil) {\n super.dismiss(animated: animated, completion: completion)\n actionSheetController?.dismiss(animated: animated)\n }\n}",
"tokens": 0,
"firstFile": {
"name": "Experience Upgrades/Upgrade Views/ContactPermissionReminderMegaphone.swift",
"start": 62,
"end": 76,
"startLoc": {
"line": 62,
"column": 36,
"position": 391
},
"endLoc": {
"line": 76,
"column": 2,
"position": 515
}
},
"secondFile": {
"name": "Experience Upgrades/Upgrade Views/NotificationPermissionReminderMegaphone.swift",
"start": 68,
"end": 82,
"startLoc": {
"line": 68,
"column": 41,
"position": 431
},
"endLoc": {
"line": 82,
"column": 2,
"position": 555
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "@available(*, unavailable, message:\"use other constructor instead.\")\n required init?(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n @available(*, unavailable, message:\"use other constructor instead.\")\n override init(frame: CGRect) {\n notImplemented()\n }\n\n init(mode",
"tokens": 0,
"firstFile": {
"name": "views/ReminderView.swift",
"start": 33,
"end": 43,
"startLoc": {
"line": 33,
"column": 5,
"position": 147
},
"endLoc": {
"line": 43,
"column": 5,
"position": 226
}
},
"secondFile": {
"name": "views/TypingIndicatorView.swift",
"start": 111,
"end": 121,
"startLoc": {
"line": 111,
"column": 9,
"position": 704
},
"endLoc": {
"line": 121,
"column": 8,
"position": 783
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": ")\n }\n\n @available(*, unavailable, message: \"Unimplemented\")\n required public init?(coder aDecoder: NSCoder) {\n notImplemented()\n }\n\n var image: UIImage? {\n get { return imageView.image }\n set {\n imageView.image = newValue\n imageView.backgroundColor = newValue == nil ? loadingColor",
"tokens": 0,
"firstFile": {
"name": "views/PhotoGridViewCell.swift",
"start": 126,
"end": 138,
"startLoc": {
"line": 126,
"column": 20,
"position": 1016
},
"endLoc": {
"line": 138,
"column": 13,
"position": 1118
}
},
"secondFile": {
"name": "ViewControllers/Attachment Keyboard/RecentPhotoCollectionView.swift",
"start": 298,
"end": 310,
"startLoc": {
"line": 298,
"column": 2,
"position": 2458
},
"endLoc": {
"line": 310,
"column": 6,
"position": 2560
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "(coder: NSCoder) {\n fatalError(\"init(coder:) has not been implemented\")\n }\n\n required init(dictionary dictionaryValue: [String: Any]!) throws {\n fatalError(\"init(dictionary:) has not been implemented\")\n }\n\n public override var shouldBeSaved: Bool {\n return false\n }\n\n override func anyWillInsert(with transaction: SDSAnyWriteTransaction) {\n owsFailDebug(\"shouldn't save mock message\")\n }\n\n class",
"tokens": 0,
"firstFile": {
"name": "views/MockConversationView.swift",
"start": 233,
"end": 249,
"startLoc": {
"line": 233,
"column": 2,
"position": 1630
},
"endLoc": {
"line": 249,
"column": 6,
"position": 1733
}
},
"secondFile": {
"name": "views/MockConversationView.swift",
"start": 208,
"end": 223,
"startLoc": {
"line": 208,
"column": 5,
"position": 1454
},
"endLoc": {
"line": 223,
"column": 2,
"position": 1555
}
}
},
{
"format": "swift",
"lines": 20,
"fragment": "let panGestureRecognizer = DirectionalPanGestureRecognizer(direction: .vertical, target: self, action: #selector(handlePan))\n view.addGestureRecognizer(panGestureRecognizer)\n panGestureRecognizer.delegate = self\n\n // We also want to handle the pan gesture for the table\n // view, so we can do a nice scroll to dismiss gesture, and\n // so we can transfer any initial scrolling into maximizing\n // the view.\n tableView.panGestureRecognizer.addTarget(self, action: #selector(handlePan))\n\n handle.backgroundColor = .ows_whiteAlpha80\n handle.autoSetDimensions(to: CGSize(width: 56, height: 5))\n handle.layer.cornerRadius = 5 / 2\n view.addSubview(handle)\n handle.autoHCenterInSuperview()\n handle.autoPinEdge(.bottom, to: .top, of: contentView, withOffset: -8)\n }\n\n @objc func handlePan(_ sender: UIPanGestureRecognizer) {\n switch",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/SafetyNumberConfirmationSheet.swift",
"start": 284,
"end": 303,
"startLoc": {
"line": 284,
"column": 9,
"position": 2416
},
"endLoc": {
"line": 303,
"column": 7,
"position": 2612
}
},
"secondFile": {
"name": "Calls/UserInterface/Group/GroupCallMemberSheet.swift",
"start": 123,
"end": 206,
"startLoc": {
"line": 123,
"column": 9,
"position": 943
},
"endLoc": {
"line": 206,
"column": 4,
"position": 1587
}
}
},
{
"format": "swift",
"lines": 25,
"fragment": ": UIGestureRecognizerDelegate {\n func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UITapGestureRecognizer:\n let point = gestureRecognizer.location(in: view)\n guard !contentView.frame.contains(point) else { return false }\n return true\n default:\n return true\n }\n }\n\n func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {\n switch gestureRecognizer {\n case is UIPanGestureRecognizer:\n return tableView.panGestureRecognizer == otherGestureRecognizer\n default:\n return false\n }\n }\n}\n\n// MARK: -\n\nprivate class SafetyNumberConfirmationAnimationController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/SafetyNumberConfirmationSheet.swift",
"start": 522,
"end": 546,
"startLoc": {
"line": 522,
"column": 30,
"position": 4449
},
"endLoc": {
"line": 546,
"column": 44,
"position": 4630
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 583,
"end": 449,
"startLoc": {
"line": 583,
"column": 21,
"position": 4539
},
"endLoc": {
"line": 449,
"column": 40,
"position": 3716
}
}
},
{
"format": "swift",
"lines": 40,
"fragment": "else { return nil }\n return vc.backdropView\n }\n\n override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {\n super.init(presentedViewController: presentedViewController, presenting: presentingViewController)\n backdropView?.backgroundColor = Theme.backdropColor\n }\n\n override func presentationTransitionWillBegin() {\n guard let containerView = containerView, let backdropView = backdropView else { return }\n backdropView.alpha = 0\n containerView.addSubview(backdropView)\n backdropView.autoPinEdgesToSuperviewEdges()\n containerView.layoutIfNeeded()\n\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 1\n }, completion: nil)\n }\n\n override func dismissalTransitionWillBegin() {\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView?.alpha = 0\n }, completion: { _ in\n self.backdropView?.removeFromSuperview()\n })\n }\n\n override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n guard let presentedView = presentedView else { return }\n coordinator.animate(alongsideTransition: { _ in\n presentedView.frame = self.frameOfPresentedViewInContainerView\n presentedView.layoutIfNeeded()\n }, completion: nil)\n }\n}\n\nextension SafetyNumberConfirmationSheet",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/SafetyNumberConfirmationSheet.swift",
"start": 549,
"end": 588,
"startLoc": {
"line": 549,
"column": 2,
"position": 4665
},
"endLoc": {
"line": 588,
"column": 30,
"position": 5037
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 610,
"end": 649,
"startLoc": {
"line": 610,
"column": 2,
"position": 4755
},
"endLoc": {
"line": 649,
"column": 21,
"position": 5127
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": ": UITextFieldDelegate {\n public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {\n let hasPendingChanges: Bool\n if pinType == .numeric {\n ViewControllerUtils.ows2FAPINTextField(textField, shouldChangeCharactersIn: range, replacementString: string)\n hasPendingChanges = false\n } else {\n hasPendingChanges = true\n }\n\n // Reset the validation state to clear errors, since the user is trying again\n validationState",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinSetupViewController.swift",
"start": 659,
"end": 670,
"startLoc": {
"line": 659,
"column": 23,
"position": 5381
},
"endLoc": {
"line": 670,
"column": 16,
"position": 5494
}
},
"secondFile": {
"name": "ViewControllers/Registration/Onboarding2FAViewController.swift",
"start": 472,
"end": 483,
"startLoc": {
"line": 472,
"column": 28,
"position": 3492
},
"endLoc": {
"line": 483,
"column": 13,
"position": 3605
}
}
},
{
"format": "swift",
"lines": 7,
"fragment": "pinTextField.isSecureTextEntry = true\n pinTextField.defaultTextAttributes.updateValue(5, forKey: .kern)\n pinTextField.keyboardAppearance = Theme.keyboardAppearance\n pinTextField.setContentHuggingHorizontalLow()\n pinTextField.setCompressionResistanceHorizontalLow()\n pinTextField.autoSetDimension(.height, toSize: 40)\n pinTextField.accessibilityIdentifier = \"pinReminder.pinTextField\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 123,
"end": 129,
"startLoc": {
"line": 123,
"column": 9,
"position": 948
},
"endLoc": {
"line": 129,
"column": 27,
"position": 1020
}
},
"secondFile": {
"name": "ViewControllers/Registration/Onboarding2FAViewController.swift",
"start": 84,
"end": 90,
"startLoc": {
"line": 84,
"column": 9,
"position": 633
},
"endLoc": {
"line": 90,
"column": 30,
"position": 705
}
}
},
{
"format": "swift",
"lines": 16,
"fragment": "()\n\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView.alpha = 1\n }, completion: nil)\n }\n\n override func dismissalTransitionWillBegin() {\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView.alpha = 0\n }, completion: { _ in\n self.backdropView.removeFromSuperview()\n })\n }\n\n override",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 324,
"end": 339,
"startLoc": {
"line": 324,
"column": 15,
"position": 2689
},
"endLoc": {
"line": 339,
"column": 9,
"position": 2805
}
},
"secondFile": {
"name": "ViewControllers/Stickers/StickerPackViewController.swift",
"start": 442,
"end": 457,
"startLoc": {
"line": 442,
"column": 29,
"position": 3482
},
"endLoc": {
"line": 457,
"column": 4,
"position": 3598
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": ".removeFromSuperview()\n })\n }\n\n override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n guard let presentedView = presentedView else { return }\n coordinator.animate(alongsideTransition: { _ in\n presentedView.frame = self.frameOfPresentedViewInContainerView\n presentedView.layoutIfNeeded()\n }, completion: nil)\n }\n}\n\nextension PinReminderViewController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 335,
"end": 349,
"startLoc": {
"line": 335,
"column": 13,
"position": 2791
},
"endLoc": {
"line": 349,
"column": 26,
"position": 2915
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/Reactions Details/ReactionsDetailSheet.swift",
"start": 635,
"end": 649,
"startLoc": {
"line": 635,
"column": 2,
"position": 5003
},
"endLoc": {
"line": 649,
"column": 21,
"position": 5127
}
}
},
{
"format": "swift",
"lines": 29,
"fragment": "private let containerView = UIView()\n private let pinTextField = UITextField()\n\n private lazy var pinStrokeNormal = pinTextField.addBottomStroke()\n private lazy var pinStrokeError = pinTextField.addBottomStroke(color: .ows_accentRed, strokeWidth: 2)\n private let validationWarningLabel = UILabel()\n\n enum ValidationState {\n case valid\n case tooShort\n case mismatch\n\n var isInvalid: Bool {\n return self != .valid\n }\n }\n private var validationState: ValidationState = .valid {\n didSet {\n updateValidationWarnings()\n\n if validationState.isInvalid {\n hasGuessedWrong = true\n }\n }\n }\n private var hasGuessedWrong = false\n\n @objc\n init(title",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 15,
"end": 43,
"startLoc": {
"line": 15,
"column": 5,
"position": 81
},
"endLoc": {
"line": 43,
"column": 6,
"position": 286
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 12,
"end": 40,
"startLoc": {
"line": 12,
"column": 5,
"position": 51
},
"endLoc": {
"line": 40,
"column": 18,
"position": 256
}
}
},
{
"format": "swift",
"lines": 63,
"fragment": "self.completionHandler = completionHandler\n super.init()\n modalPresentationStyle = .custom\n transitioningDelegate = self\n }\n\n public override func viewWillAppear(_ animated: Bool) {\n super.viewWillAppear(animated)\n pinTextField.becomeFirstResponder()\n }\n\n public override func viewDidAppear(_ animated: Bool) {\n super.viewDidAppear(animated)\n\n // For now, the design only allows for portrait layout on non-iPads\n if !UIDevice.current.isIPad && CurrentAppContext().interfaceOrientation != .portrait {\n UIDevice.current.ows_setOrientation(.portrait)\n }\n }\n\n public override func viewWillDisappear(_ animated: Bool) {\n super.viewWillDisappear(animated)\n pinTextField.resignFirstResponder()\n }\n\n override public var preferredStatusBarStyle: UIStatusBarStyle {\n return Theme.isDarkThemeEnabled ? .lightContent : .default\n }\n\n public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {\n return UIDevice.current.isIPad ? .all : .portrait\n }\n\n override public func loadView() {\n view = UIView()\n view.backgroundColor = .clear\n\n containerView.backgroundColor = Theme.backgroundColor\n\n view.addSubview(containerView)\n containerView.autoPinWidthToSuperview()\n autoPinView(toBottomOfViewControllerOrKeyboard: containerView, avoidNotch: true)\n\n // We want the background to extend to the bottom of the screen\n // behind the safe area, so we add that inset to our bottom inset\n // instead of pinning this view to the safe area\n let safeAreaBackdrop = UIView()\n safeAreaBackdrop.backgroundColor = Theme.backgroundColor\n view.addSubview(safeAreaBackdrop)\n safeAreaBackdrop.autoPinEdge(.top, to: .bottom, of: containerView)\n safeAreaBackdrop.autoPinWidthToSuperview()\n // We don't know the safe area insets, so just guess a big number that will extend off screen\n safeAreaBackdrop.autoSetDimension(.height, toSize: 150)\n\n // Title\n\n let titleLabel = UILabel()\n titleLabel.textColor = Theme.primaryTextColor\n titleLabel.font = UIFont.ows_dynamicTypeTitle3Clamped.ows_semibold\n titleLabel.numberOfLines = 0\n titleLabel.lineBreakMode = .byWordWrapping\n titleLabel.textAlignment = .center\n titleLabel.text = titleText",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 47,
"end": 109,
"startLoc": {
"line": 47,
"column": 9,
"position": 350
},
"endLoc": {
"line": 109,
"column": 10,
"position": 844
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 41,
"end": 103,
"startLoc": {
"line": 41,
"column": 9,
"position": 278
},
"endLoc": {
"line": 103,
"column": 18,
"position": 772
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": "pinTextField.delegate = self\n pinTextField.keyboardType = KeyBackupService.currentPinType == .alphanumeric ? .default : .asciiCapableNumberPad\n pinTextField.textColor = Theme.primaryTextColor\n pinTextField.font = .ows_dynamicTypeBodyClamped\n pinTextField.textAlignment = .center\n pinTextField.isSecureTextEntry = true\n pinTextField.defaultTextAttributes.updateValue(5, forKey: .kern)\n pinTextField.keyboardAppearance = Theme.keyboardAppearance\n pinTextField.setContentHuggingHorizontalLow()\n pinTextField.setCompressionResistanceHorizontalLow()\n pinTextField.autoSetDimension(.height, toSize: 40)\n pinTextField.accessibilityIdentifier = \"pinConfirmation.pinTextField\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 124,
"end": 135,
"startLoc": {
"line": 124,
"column": 9,
"position": 936
},
"endLoc": {
"line": 135,
"column": 31,
"position": 1074
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 118,
"end": 90,
"startLoc": {
"line": 118,
"column": 9,
"position": 882
},
"endLoc": {
"line": 90,
"column": 30,
"position": 705
}
}
},
{
"format": "swift",
"lines": 19,
"fragment": "let pinStack = UIStackView(arrangedSubviews: [\n pinTextField,\n UIView.spacer(withHeight: 10),\n validationWarningLabel\n ])\n pinStack.axis = .vertical\n pinStack.alignment = .fill\n\n let pinStackRow = UIView()\n pinStackRow.addSubview(pinStack)\n pinStack.autoHCenterInSuperview()\n pinStack.autoPinHeightToSuperview()\n pinStack.autoSetDimension(.width, toSize: 227)\n pinStackRow.setContentHuggingVerticalHigh()\n\n let font = UIFont.ows_dynamicTypeBodyClamped.ows_semibold\n let buttonHeight = OWSFlatButton.heightForFont(font)\n let submitButton = OWSFlatButton.button(\n title: actionText",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 142,
"end": 160,
"startLoc": {
"line": 142,
"column": 9,
"position": 1119
},
"endLoc": {
"line": 160,
"column": 11,
"position": 1275
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 138,
"end": 156,
"startLoc": {
"line": 138,
"column": 9,
"position": 1084
},
"endLoc": {
"line": 156,
"column": 18,
"position": 1240
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "])\n stackView.axis = .vertical\n stackView.alignment = .fill\n stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 16, right: 32)\n stackView.isLayoutMarginsRelativeArrangement = true\n containerView.addSubview(stackView)\n stackView.autoPinEdgesToSuperviewEdges()\n\n // Ensure whitespace is balanced, so inputs are vertically centered.\n topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)\n topSpacer.autoSetDimension(.height, toSize: 20, relation: .greaterThanOrEqual)\n\n updateValidationWarnings",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 191,
"end": 203,
"startLoc": {
"line": 191,
"column": 9,
"position": 1535
},
"endLoc": {
"line": 203,
"column": 25,
"position": 1665
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 188,
"end": 200,
"startLoc": {
"line": 188,
"column": 9,
"position": 1517
},
"endLoc": {
"line": 200,
"column": 4,
"position": 1647
}
}
},
{
"format": "swift",
"lines": 22,
"fragment": ")\n\n updateValidationWarnings()\n }\n\n public override func viewDidLayoutSubviews() {\n super.viewDidLayoutSubviews()\n\n let cornerRadius: CGFloat = 16\n let path = UIBezierPath(\n roundedRect: containerView.bounds,\n byRoundingCorners: [.topLeft, .topRight],\n cornerRadii: CGSize(square: cornerRadius)\n )\n let shapeLayer = CAShapeLayer()\n shapeLayer.path = path.cgPath\n containerView.layer.mask = shapeLayer\n }\n\n // MARK: - Events\n\n @objc func cancelPressed",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 201,
"end": 222,
"startLoc": {
"line": 201,
"column": 19,
"position": 1661
},
"endLoc": {
"line": 222,
"column": 14,
"position": 1800
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 206,
"end": 227,
"startLoc": {
"line": 206,
"column": 2,
"position": 1757
},
"endLoc": {
"line": 227,
"column": 14,
"position": 1896
}
}
},
{
"format": "swift",
"lines": 25,
"fragment": "}\n\n private func updateValidationWarnings() {\n AssertIsOnMainThread()\n\n pinStrokeNormal.isHidden = validationState.isInvalid\n pinStrokeError.isHidden = !validationState.isInvalid\n validationWarningLabel.isHidden = !validationState.isInvalid\n\n switch validationState {\n case .tooShort:\n validationWarningLabel.text = NSLocalizedString(\"PIN_REMINDER_TOO_SHORT_ERROR\",\n comment: \"Label indicating that the attempted PIN is too short\")\n case .mismatch:\n validationWarningLabel.text = NSLocalizedString(\"PIN_REMINDER_MISMATCH_ERROR\",\n comment: \"Label indicating that the attempted PIN does not match the user's PIN\")\n default:\n break\n }\n }\n}\n\n// MARK: -\n\nprivate class PinConfirmationPresentationController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 255,
"end": 279,
"startLoc": {
"line": 255,
"column": 5,
"position": 2069
},
"endLoc": {
"line": 279,
"column": 38,
"position": 2207
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 284,
"end": 308,
"startLoc": {
"line": 284,
"column": 5,
"position": 2391
},
"endLoc": {
"line": 308,
"column": 34,
"position": 2529
}
}
},
{
"format": "swift",
"lines": 42,
"fragment": ": UIPresentationController {\n let backdropView = UIView()\n\n override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {\n super.init(presentedViewController: presentedViewController, presenting: presentingViewController)\n\n let alpha: CGFloat = Theme.isDarkThemeEnabled ? 0.7 : 0.6\n backdropView.backgroundColor = UIColor.black.withAlphaComponent(alpha)\n }\n\n override func presentationTransitionWillBegin() {\n guard let containerView = containerView else { return }\n\n backdropView.alpha = 0\n containerView.addSubview(backdropView)\n backdropView.autoPinEdgesToSuperviewEdges()\n containerView.layoutIfNeeded()\n\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView.alpha = 1\n }, completion: nil)\n }\n\n override func dismissalTransitionWillBegin() {\n presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in\n self.backdropView.alpha = 0\n }, completion: { _ in\n self.backdropView.removeFromSuperview()\n })\n }\n\n override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n super.viewWillTransition(to: size, with: coordinator)\n guard let presentedView = presentedView else { return }\n coordinator.animate(alongsideTransition: { _ in\n presentedView.frame = self.frameOfPresentedViewInContainerView\n presentedView.layoutIfNeeded()\n }, completion: nil)\n }\n}\n\nextension PinConfirmationViewController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 279,
"end": 320,
"startLoc": {
"line": 279,
"column": 38,
"position": 2208
},
"endLoc": {
"line": 320,
"column": 30,
"position": 2593
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 308,
"end": 649,
"startLoc": {
"line": 308,
"column": 34,
"position": 2530
},
"endLoc": {
"line": 649,
"column": 21,
"position": 5127
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": ": UITextFieldDelegate {\n public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {\n let hasPendingChanges: Bool\n if KeyBackupService.currentPinType == .alphanumeric {\n hasPendingChanges = true\n } else {\n ViewControllerUtils.ows2FAPINTextField(textField, shouldChangeCharactersIn: range, replacementString: string)\n hasPendingChanges = false\n }",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/OWSPinConfirmationViewController.swift",
"start": 328,
"end": 336,
"startLoc": {
"line": 328,
"column": 30,
"position": 2665
},
"endLoc": {
"line": 336,
"column": 2,
"position": 2773
}
},
"secondFile": {
"name": "ViewControllers/OWSPinReminderViewController.swift",
"start": 357,
"end": 367,
"startLoc": {
"line": 357,
"column": 26,
"position": 2987
},
"endLoc": {
"line": 367,
"column": 15,
"position": 3099
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": "guard let interaction = TSInteraction.anyFetch(uniqueId: interactionId,\n transaction: transaction) else {\n owsFailDebug(\"Missing interaction.\")\n return nil\n }\n guard let thread = TSThread.anyFetch(uniqueId: interaction.uniqueThreadId,\n transaction: transaction) else {\n owsFailDebug(\"Missing thread.\")\n return nil\n }\n return CVLoader.buildStandaloneRenderItem(interaction: interaction,\n thread: thread,\n containerView: containerView",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MessageDetailViewController.swift",
"start": 335,
"end": 347,
"startLoc": {
"line": 335,
"column": 13,
"position": 2546
},
"endLoc": {
"line": 347,
"column": 14,
"position": 2659
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/MediaPageViewController.swift",
"start": 627,
"end": 639,
"startLoc": {
"line": 627,
"column": 13,
"position": 4911
},
"endLoc": {
"line": 639,
"column": 5,
"position": 5024
}
}
},
{
"format": "swift",
"lines": 49,
"fragment": ".albumItemView(forAttachment: galleryItem.attachmentStream) else {\n owsFailDebug(\"itemView was unexpectedly nil\")\n return nil\n }\n\n guard let mediaSuperview = mediaView.superview else {\n owsFailDebug(\"mediaSuperview was unexpectedly nil\")\n return nil\n }\n\n let presentationFrame = coordinateSpace.convert(mediaView.frame, from: mediaSuperview)\n\n // TODO better corner rounding.\n return MediaPresentationContext(mediaView: mediaView,\n presentationFrame: presentationFrame,\n cornerRadius: kOWSMessageCellCornerRadius_Small * 2)\n }\n\n func snapshotOverlayView(in coordinateSpace: UICoordinateSpace) -> (UIView, CGRect)? {\n return nil\n }\n\n func mediaWillDismiss(toContext: MediaPresentationContext) {\n // To avoid flicker when transition view is animated over the message bubble,\n // we initially hide the overlaying elements and fade them in.\n let mediaOverlayViews = toContext.mediaOverlayViews\n for mediaOverlayView in mediaOverlayViews {\n mediaOverlayView.alpha = 0\n }\n }\n\n func mediaDidDismiss(toContext: MediaPresentationContext) {\n // To avoid flicker when transition view is animated over the message bubble,\n // we initially hide the overlaying elements and fade them in.\n let mediaOverlayViews = toContext.mediaOverlayViews\n let duration: TimeInterval = kIsDebuggingMediaPresentationAnimations ? 1.5 : 0.2\n UIView.animate(\n withDuration: duration,\n animations: {\n for mediaOverlayView in mediaOverlayViews {\n mediaOverlayView.alpha = 1\n }\n })\n }\n}\n\n// MARK: -\n\nextension",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MessageDetailViewController.swift",
"start": 602,
"end": 650,
"startLoc": {
"line": 602,
"column": 9,
"position": 4655
},
"endLoc": {
"line": 650,
"column": 10,
"position": 4973
}
},
"secondFile": {
"name": "ViewControllers/ConversationView/ConversationViewController+OWS.swift",
"start": 392,
"end": 438,
"startLoc": {
"line": 392,
"column": 12,
"position": 2643
},
"endLoc": {
"line": 438,
"column": 6,
"position": 2959
}
}
},
{
"format": "swift",
"lines": 54,
"fragment": ": CVComponentDelegate {\n\n // MARK: - Long Press\n\n // TODO:\n func cvc_didLongPressTextViewItem(_ cell: CVCell,\n itemViewModel: CVItemViewModelImpl,\n shouldAllowReply: Bool) {}\n\n // TODO:\n func cvc_didLongPressMediaViewItem(_ cell: CVCell,\n itemViewModel: CVItemViewModelImpl,\n shouldAllowReply: Bool) {}\n\n // TODO:\n func cvc_didLongPressQuote(_ cell: CVCell,\n itemViewModel: CVItemViewModelImpl,\n shouldAllowReply: Bool) {}\n\n // TODO:\n func cvc_didLongPressSystemMessage(_ cell: CVCell,\n itemViewModel: CVItemViewModelImpl) {}\n\n // TODO:\n func cvc_didLongPressSticker(_ cell: CVCell,\n itemViewModel: CVItemViewModelImpl,\n shouldAllowReply: Bool) {}\n\n // TODO:\n func cvc_didChangeLongpress(_ itemViewModel: CVItemViewModelImpl) {}\n\n // TODO:\n func cvc_didEndLongpress(_ itemViewModel: CVItemViewModelImpl) {}\n\n // TODO:\n func cvc_didCancelLongpress(_ itemViewModel: CVItemViewModelImpl) {}\n\n // MARK: -\n\n // TODO:\n func cvc_didTapReplyToItem(_ itemViewModel: CVItemViewModelImpl) {}\n\n // TODO:\n func cvc_didTapSenderAvatar(_ interaction: TSInteraction) {}\n\n // TODO:\n func cvc_shouldAllowReplyForItem(_ itemViewModel: CVItemViewModelImpl) -> Bool { false }\n\n // TODO:\n func cvc_didTapReactions(reactionState: InteractionReactionState,\n message: TSMessage) {}\n\n func cvc_didTapTruncatedTextMessage(_ itemViewModel: CVItemViewModelImpl) {\n AssertIsOnMainThread",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MessageDetailViewController.swift",
"start": 751,
"end": 804,
"startLoc": {
"line": 751,
"column": 28,
"position": 5644
},
"endLoc": {
"line": 804,
"column": 21,
"position": 5991
}
},
"secondFile": {
"name": "views/MockConversationView.swift",
"start": 277,
"end": 315,
"startLoc": {
"line": 277,
"column": 21,
"position": 1930
},
"endLoc": {
"line": 315,
"column": 2,
"position": 2235
}
}
},
{
"format": "swift",
"lines": 70,
"fragment": "}\n\n func cvc_didTapMention(_ mention: Mention) {}\n\n // MARK: - Selection\n\n // TODO:\n var isShowingSelectionUI: Bool { false }\n\n // TODO:\n func cvc_isMessageSelected(_ interaction: TSInteraction) -> Bool { false }\n\n // TODO:\n func cvc_didSelectViewItem(_ itemViewModel: CVItemViewModelImpl) {}\n\n // TODO:\n func cvc_didDeselectViewItem(_ itemViewModel: CVItemViewModelImpl) {}\n\n // MARK: - System Cell\n\n // TODO:\n func cvc_didTapNonBlockingIdentityChange(_ address: SignalServiceAddress) {}\n\n // TODO:\n func cvc_didTapInvalidIdentityKeyErrorMessage(_ message: TSInvalidIdentityKeyErrorMessage) {}\n\n // TODO:\n func cvc_didTapCorruptedMessage(_ message: TSErrorMessage) {}\n\n // TODO:\n func cvc_didTapSessionRefreshMessage(_ message: TSErrorMessage) {}\n\n // See: resendGroupUpdate\n // TODO:\n func cvc_didTapResendGroupUpdateForErrorMessage(_ errorMessage: TSErrorMessage) {}\n\n // TODO:\n func cvc_didTapShowFingerprint(_ address: SignalServiceAddress) {}\n\n // TODO:\n func cvc_didTapIndividualCall(_ call: TSCall) {}\n\n // TODO:\n func cvc_didTapGroupCall() {}\n\n // TODO:\n func cvc_didTapFailedOutgoingMessage(_ message: TSOutgoingMessage) {}\n\n // TODO:\n func cvc_didTapShowGroupMigrationLearnMoreActionSheet(infoMessage: TSInfoMessage,\n oldGroupModel: TSGroupModel,\n newGroupModel: TSGroupModel) {}\n\n func cvc_didTapGroupInviteLinkPromotion(groupModel: TSGroupModel) {}\n\n // TODO:\n func cvc_didTapShowConversationSettings() {}\n\n // TODO:\n func cvc_didTapShowConversationSettingsAndShowMemberRequests() {}\n\n // TODO:\n func cvc_didTapShowUpgradeAppUI() {}\n\n // TODO:\n func cvc_didTapUpdateSystemContact(_ address: SignalServiceAddress,\n newNameComponents: PersonNameComponents) {}\n\n func cvc_didTapViewOnceAttachment(_ interaction: TSInteraction) {\n guard",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/MessageDetailViewController.swift",
"start": 883,
"end": 952,
"startLoc": {
"line": 883,
"column": 5,
"position": 6634
},
"endLoc": {
"line": 952,
"column": 6,
"position": 7057
}
},
"secondFile": {
"name": "views/MockConversationView.swift",
"start": 343,
"end": 392,
"startLoc": {
"line": 343,
"column": 2,
"position": 2458
},
"endLoc": {
"line": 392,
"column": 2,
"position": 2822
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "threads: [TSThread]) {\n guard threads.count == 1 else {\n return\n }\n guard let thread = threads.first else {\n owsFailDebug(\"Missing thread.\")\n return\n }\n guard thread.uniqueId != itemViewModel.interaction.uniqueThreadId else {\n return\n }\n SignalApp.shared().presentConversation(for: thread, animated: true)\n }\n}",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/LongTextViewController.swift",
"start": 208,
"end": 221,
"startLoc": {
"line": 208,
"column": 2,
"position": 1422
},
"endLoc": {
"line": 221,
"column": 2,
"position": 1531
}
},
"secondFile": {
"name": "ViewControllers/MediaGallery/MediaPageViewController.swift",
"start": 922,
"end": 935,
"startLoc": {
"line": 922,
"column": 28,
"position": 7221
},
"endLoc": {
"line": 935,
"column": 2,
"position": 7330
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": ") {\n presentingViewController?.dismiss(animated: true) {\n switch result {\n case .failed:\n let warning = ActionSheetController(title: nil, message: NSLocalizedString(\"SEND_INVITE_FAILURE\", comment: \"Alert body after invite failed\"))\n warning.addAction(OWSActionSheets.dismissAction)\n self.presentingViewController?.present(warning, animated: true, completion: nil)\n case .sent:\n Logger.debug(\"user successfully invited their friends via mail.\"",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/InviteFlow.swift",
"start": 314,
"end": 322,
"startLoc": {
"line": 314,
"column": 2,
"position": 2759
},
"endLoc": {
"line": 322,
"column": 52,
"position": 2866
}
},
"secondFile": {
"name": "ViewControllers/InviteFlow.swift",
"start": 254,
"end": 262,
"startLoc": {
"line": 254,
"column": 21,
"position": 2203
},
"endLoc": {
"line": 262,
"column": 51,
"position": 2310
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": "()\n actionSheetController.customHeader = self\n actionSheetController.isCancelable = true\n fromViewController.presentActionSheet(actionSheetController)\n self.actionSheetController = actionSheetController\n }\n\n @objc\n public func configure() {\n let subviews = buildContents()\n\n let stackView = UIStackView(arrangedSubviews: subviews)\n stackView.axis = .vertical\n stackView.alignment = .fill\n stackView.layoutMargins = UIEdgeInsets(top: 24",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/GroupLinkPromotionActionSheet.swift",
"start": 42,
"end": 56,
"startLoc": {
"line": 42,
"column": 18,
"position": 237
},
"endLoc": {
"line": 56,
"column": 3,
"position": 352
}
},
"secondFile": {
"name": "ViewControllers/GroupMigrationActionSheet.swift",
"start": 67,
"end": 81,
"startLoc": {
"line": 67,
"column": 22,
"position": 476
},
"endLoc": {
"line": 81,
"column": 3,
"position": 591
}
}
},
{
"format": "swift",
"lines": 12,
"fragment": "{ thread in\n let contactShareCopy = contactShare.copyForResending()\n\n if let avatarImage = contactShareCopy.avatarImage {\n self.databaseStorage.write { transaction in\n contactShareCopy.dbRecord.saveAvatarImage(avatarImage, transaction: transaction)\n }\n }\n\n self.send(contactShare: contactShareCopy, thread: thread)\n }\n case .stickerMessage",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ForwardMessageNavigationController.swift",
"start": 182,
"end": 193,
"startLoc": {
"line": 182,
"column": 2,
"position": 1263
},
"endLoc": {
"line": 193,
"column": 15,
"position": 1358
}
},
"secondFile": {
"name": "ViewControllers/SendMessageFlow.swift",
"start": 349,
"end": 359,
"startLoc": {
"line": 349,
"column": 2,
"position": 2569
},
"endLoc": {
"line": 359,
"column": 17,
"position": 2663
}
}
},
{
"format": "swift",
"lines": 28,
"fragment": "}\n }\n\n func threads(for conversationItems: [ConversationItem]) -> Promise<[TSThread]> {\n return DispatchQueue.global().async(.promise) {\n guard conversationItems.count > 0 else {\n throw OWSAssertionError(\"No recipients.\")\n }\n\n var threads: [TSThread] = []\n\n self.databaseStorage.write { transaction in\n for conversation in conversationItems {\n guard let thread = conversation.thread(transaction: transaction) else {\n owsFailDebug(\"Missing thread for conversation\")\n continue\n }\n threads.append(thread)\n }\n }\n return threads\n }\n }\n}\n\n// MARK: -\n\nextension ForwardMessageNavigationController",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ForwardMessageNavigationController.swift",
"start": 311,
"end": 338,
"startLoc": {
"line": 311,
"column": 9,
"position": 2382
},
"endLoc": {
"line": 338,
"column": 35,
"position": 2567
}
},
"secondFile": {
"name": "ViewControllers/SendMessageFlow.swift",
"start": 426,
"end": 453,
"startLoc": {
"line": 426,
"column": 9,
"position": 3313
},
"endLoc": {
"line": 453,
"column": 16,
"position": 3498
}
}
},
{
"format": "swift",
"lines": 27,
"fragment": ": ConversationPickerDelegate {\n var selectedConversationsForConversationPicker: [ConversationItem] {\n return selectedConversations\n }\n\n func conversationPicker(_ conversationPickerViewController: ConversationPickerViewController,\n didSelectConversation conversation: ConversationItem) {\n self.selectedConversations.append(conversation)\n }\n\n func conversationPicker(_ conversationPickerViewController: ConversationPickerViewController,\n didDeselectConversation conversation: ConversationItem) {\n self.selectedConversations = self.selectedConversations.filter {\n $0.messageRecipient != conversation.messageRecipient\n }\n }\n\n func conversationPickerDidCompleteSelection(_ conversationPickerViewController: ConversationPickerViewController) {\n approve()\n }\n\n func conversationPickerCanCancel(_ conversationPickerViewController: ConversationPickerViewController) -> Bool {\n return true\n }\n\n func conversationPickerDidCancel(_ conversationPickerViewController: ConversationPickerViewController) {\n forwardMessageDelegate",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ForwardMessageNavigationController.swift",
"start": 338,
"end": 364,
"startLoc": {
"line": 338,
"column": 35,
"position": 2568
},
"endLoc": {
"line": 364,
"column": 23,
"position": 2760
}
},
"secondFile": {
"name": "ViewControllers/SendMessageFlow.swift",
"start": 453,
"end": 479,
"startLoc": {
"line": 453,
"column": 16,
"position": 3499
},
"endLoc": {
"line": 479,
"column": 14,
"position": 3691
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": ".map { $0.title }\n }\n\n var attachmentApprovalMentionableAddresses: [SignalServiceAddress] {\n guard selectedConversations.count == 1,\n case .group(let groupThreadId) = selectedConversations.first?.messageRecipient,\n let groupThread = databaseStorage.uiRead(block: { transaction in\n return TSGroupThread.anyFetchGroupThread(uniqueId: groupThreadId, transaction: transaction)\n }),\n Mention.threadAllowsMentionSend(groupThread) else { return [] }\n return groupThread.recipientAddresses\n }\n}\n\n// MARK: -\n\nextension",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ForwardMessageNavigationController.swift",
"start": 473,
"end": 489,
"startLoc": {
"line": 473,
"column": 43,
"position": 3568
},
"endLoc": {
"line": 489,
"column": 10,
"position": 3708
}
},
"secondFile": {
"name": "ViewControllers/SendMessageFlow.swift",
"start": 600,
"end": 616,
"startLoc": {
"line": 600,
"column": 22,
"position": 4596
},
"endLoc": {
"line": 616,
"column": 7,
"position": 4736
}
}
},
{
"format": "swift",
"lines": 9,
"fragment": "view.addSubview(tableView)\n tableView.autoPinEdge(toSuperviewEdge: .top)\n tableView.autoPinEdge(toSuperviewEdge: .bottom)\n tableView.autoPinEdge(toSuperviewSafeArea: .leading)\n tableView.autoPinEdge(toSuperviewSafeArea: .trailing)\n tableView.delegate = self\n tableView.dataSource = self\n\n let",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ContactsPicker.swift",
"start": 74,
"end": 82,
"startLoc": {
"line": 74,
"column": 9,
"position": 505
},
"endLoc": {
"line": 82,
"column": 4,
"position": 580
}
},
"secondFile": {
"name": "ViewControllers/ThreadSettings/OWSAddToContactViewController.swift",
"start": 33,
"end": 40,
"startLoc": {
"line": 33,
"column": 9,
"position": 175
},
"endLoc": {
"line": 40,
"column": 2,
"position": 249
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "func addBottomButton(title: String,\n titleColor: UIColor,\n backgroundColor: UIColor,\n target: Any,\n selector: Selector) {\n let buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_semibold\n let buttonHeight = OWSFlatButton.heightForFont(buttonFont)\n let upgradeButton = OWSFlatButton.button(title: title,\n font: buttonFont,\n titleColor: titleColor,\n backgroundColor: backgroundColor,\n target: target,\n selector: selector)\n upgradeButton.autoSetDimension(.height, toSize: buttonHeight)\n subviews.append(upgradeButton)\n }\n}",
"tokens": 0,
"firstFile": {
"name": "ViewControllers/ActionSheetContentBuilder.swift",
"start": 40,
"end": 56,
"startLoc": {
"line": 40,
"column": 5,
"position": 296
},
"endLoc": {
"line": 56,
"column": 2,
"position": 441
}
},
"secondFile": {
"name": "ViewControllers/GroupMigrationActionSheet.swift",
"start": 202,
"end": 219,
"startLoc": {
"line": 202,
"column": 2,
"position": 1624
},
"endLoc": {
"line": 219,
"column": 9,
"position": 1771
}
}
},
{
"format": "swift",
"lines": 14,
"fragment": "thread: TSThread?) -> IndexPath? {\n let isPinnedThread: Bool\n if let thread = thread, pinnedThreads.orderedKeys.contains(thread.uniqueId) {\n isPinnedThread = true\n } else {\n isPinnedThread = false\n }\n\n let section = isPinnedThread ? pinnedSection : unpinnedSection\n let threadsInSection = isPinnedThread ? pinnedThreads.orderedValues : unpinnedThreads\n\n guard !threadsInSection.isEmpty else { return nil }\n\n let lastIndexPath",
"tokens": 0,
"firstFile": {
"name": "Models/ThreadMapping.swift",
"start": 181,
"end": 194,
"startLoc": {
"line": 181,
"column": 2,
"position": 1351
},
"endLoc": {
"line": 194,
"column": 14,
"position": 1483
}
},
"secondFile": {
"name": "Models/ThreadMapping.swift",
"start": 155,
"end": 168,
"startLoc": {
"line": 155,
"column": 2,
"position": 1063
},
"endLoc": {
"line": 168,
"column": 15,
"position": 1195
}
}
},
{
"format": "swift",
"lines": 11,
"fragment": "let oldThreadIds = wasPinned ? oldPinnedThreadIds : oldUnpinnedThreadIds\n let newThreadIds = isPinned ? newPinnedThreadIds : newUnpinnedThreadIds\n\n guard let oldIndex = oldThreadIds.firstIndexAsInt(of: threadId) else {\n continue\n }\n guard let newIndex = newThreadIds.firstIndexAsInt(of: threadId) else {\n throw OWSAssertionError(\"newIndex was unexpectedly nil.\")\n }\n\n let naiveThreadIdOrdering",
"tokens": 0,
"firstFile": {
"name": "Models/ThreadMapping.swift",
"start": 538,
"end": 548,
"startLoc": {
"line": 538,
"column": 13,
"position": 4377
},
"endLoc": {
"line": 548,
"column": 22,
"position": 4478
}
},
"secondFile": {
"name": "Models/ThreadMapping.swift",
"start": 471,
"end": 481,
"startLoc": {
"line": 471,
"column": 13,
"position": 3812
},
"endLoc": {
"line": 481,
"column": 11,
"position": 3913
}
}
},
{
"format": "swift",
"lines": 15,
"fragment": "else {\n logThreadIds(newPinnedThreadIds, name: \"newPinnedThreadIds\")\n logThreadIds(oldPinnedThreadIds, name: \"oldPinnedThreadIds\")\n logThreadIds(newUnpinnedThreadIds, name: \"newUnpinnedThreadIds\")\n logThreadIds(oldUnpinnedThreadIds, name: \"oldUnpinnedThreadIds\")\n logThreadIds(newlyPinnedThreadIds, name: \"newlyPinnedThreadIds\")\n logThreadIds(newlyUnpinnedThreadIds, name: \"newlyUnpinnedThreadIds\")\n logThreadIds(naivePinnedThreadIdOrdering, name: \"naivePinnedThreadIdOrdering\")\n logThreadIds(naiveUnpinnedThreadIdOrdering, name: \"naiveUnpinnedThreadIdOrdering\")\n logThreadIds(insertedThreadIds, name: \"insertedThreadIds\")\n logThreadIds(deletedThreadIds, name: \"deletedThreadIds\")\n logThreadIds(movedToNewSectionThreadIds, name: \"movedToNewSectionThreadIds\")\n logThreadIds(Array(possiblyMovedWithinSectionThreadIds), name: \"possiblyMovedWithinSectionThreadIds\")\n logThreadIds(movedThreadIds, name: \"movedThreadIds\")\n throw OWSAssertionError(\"Could not reorder unpinned contents.\"",
"tokens": 0,
"firstFile": {
"name": "Models/ThreadMapping.swift",
"start": 603,
"end": 617,
"startLoc": {
"line": 603,
"column": 2,
"position": 5009
},
"endLoc": {
"line": 617,
"column": 39,
"position": 5177
}
},
"secondFile": {
"name": "Models/ThreadMapping.swift",
"start": 586,
"end": 600,
"startLoc": {
"line": 586,
"column": 2,
"position": 4825
},
"endLoc": {
"line": 600,
"column": 37,
"position": 4993
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "(itemViewModel: CVItemViewModelImpl, shouldAllowReply: Bool, delegate: MessageActionsDelegate) -> [MessageAction] {\n var actions: [MessageAction] = []\n\n let showDetailsAction = MessageActionBuilder.showDetails(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(showDetailsAction)\n\n let deleteAction = MessageActionBuilder.deleteMessage(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(deleteAction)\n\n if itemViewModel.canShareMedia",
"tokens": 0,
"firstFile": {
"name": "Models/MessageActions.swift",
"start": 118,
"end": 127,
"startLoc": {
"line": 118,
"column": 13,
"position": 1141
},
"endLoc": {
"line": 127,
"column": 14,
"position": 1254
}
},
"secondFile": {
"name": "Models/MessageActions.swift",
"start": 88,
"end": 97,
"startLoc": {
"line": 88,
"column": 12,
"position": 862
},
"endLoc": {
"line": 97,
"column": 19,
"position": 975
}
}
},
{
"format": "swift",
"lines": 20,
"fragment": ")\n }\n\n if shouldAllowReply {\n let replyAction = MessageActionBuilder.reply(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(replyAction)\n }\n\n if itemViewModel.canForwardMessage {\n actions.append(MessageActionBuilder.forwardMessage(itemViewModel: itemViewModel, delegate: delegate))\n }\n\n let selectAction = MessageActionBuilder.selectMessage(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(selectAction)\n\n return actions\n }\n\n @objc\n class func quotedMessageActions",
"tokens": 0,
"firstFile": {
"name": "Models/MessageActions.swift",
"start": 129,
"end": 148,
"startLoc": {
"line": 129,
"column": 17,
"position": 1287
},
"endLoc": {
"line": 148,
"column": 21,
"position": 1419
}
},
"secondFile": {
"name": "Models/MessageActions.swift",
"start": 99,
"end": 118,
"startLoc": {
"line": 99,
"column": 15,
"position": 1008
},
"endLoc": {
"line": 118,
"column": 13,
"position": 1140
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "(itemViewModel: CVItemViewModelImpl, shouldAllowReply: Bool, delegate: MessageActionsDelegate) -> [MessageAction] {\n var actions: [MessageAction] = []\n\n let showDetailsAction = MessageActionBuilder.showDetails(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(showDetailsAction)\n\n let deleteAction = MessageActionBuilder.deleteMessage(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(deleteAction)\n\n if shouldAllowReply",
"tokens": 0,
"firstFile": {
"name": "Models/MessageActions.swift",
"start": 148,
"end": 157,
"startLoc": {
"line": 148,
"column": 21,
"position": 1420
},
"endLoc": {
"line": 157,
"column": 17,
"position": 1531
}
},
"secondFile": {
"name": "Models/MessageActions.swift",
"start": 88,
"end": 97,
"startLoc": {
"line": 88,
"column": 12,
"position": 862
},
"endLoc": {
"line": 97,
"column": 14,
"position": 973
}
}
},
{
"format": "swift",
"lines": 17,
"fragment": "if shouldAllowReply {\n let replyAction = MessageActionBuilder.reply(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(replyAction)\n }\n\n if itemViewModel.canForwardMessage {\n actions.append(MessageActionBuilder.forwardMessage(itemViewModel: itemViewModel, delegate: delegate))\n }\n\n let selectAction = MessageActionBuilder.selectMessage(itemViewModel: itemViewModel, delegate: delegate)\n actions.append(selectAction)\n\n return actions\n }\n\n @objc\n class func infoMessageActions",
"tokens": 0,
"firstFile": {
"name": "Models/MessageActions.swift",
"start": 157,
"end": 173,
"startLoc": {
"line": 157,
"column": 9,
"position": 1529
},
"endLoc": {
"line": 173,
"column": 19,
"position": 1654
}
},
"secondFile": {
"name": "Models/MessageActions.swift",
"start": 102,
"end": 118,
"startLoc": {
"line": 102,
"column": 9,
"position": 1015
},
"endLoc": {
"line": 118,
"column": 13,
"position": 1140
}
}
},
{
"format": "swift",
"lines": 10,
"fragment": "(userInfo: [AnyHashable: Any]) throws -> Promise<Void> {\n guard let localCallIdString = userInfo[AppNotificationUserInfoKey.localCallId] as? String else {\n throw OWSAssertionError(\"localCallIdString was unexpectedly nil\")\n }\n\n guard let localCallId = UUID(uuidString: localCallIdString) else {\n throw OWSAssertionError(\"unable to build localCallId. localCallIdString: \\(localCallIdString)\")\n }\n\n callUIAdapter.localHangupCall",
"tokens": 0,
"firstFile": {
"name": "NotificationActionHandler.swift",
"start": 65,
"end": 74,
"startLoc": {
"line": 65,
"column": 12,
"position": 462
},
"endLoc": {
"line": 74,
"column": 16,
"position": 563
}
},
"secondFile": {
"name": "NotificationActionHandler.swift",
"start": 40,
"end": 49,
"startLoc": {
"line": 40,
"column": 11,
"position": 192
},
"endLoc": {
"line": 49,
"column": 11,
"position": 293
}
}
},
{
"format": "swift",
"lines": 7,
"fragment": ") throws -> Promise<Void> {\n return firstly { () -> Promise<NotificationMessage> in\n self.notificationMessage(forUserInfo: userInfo)\n }.then(on: .global()) { (notificationMessage: NotificationMessage) -> Promise<Void> in\n let thread = notificationMessage.thread\n let interaction = notificationMessage.interaction\n guard let",
"tokens": 0,
"firstFile": {
"name": "NotificationActionHandler.swift",
"start": 130,
"end": 136,
"startLoc": {
"line": 130,
"column": 2,
"position": 1188
},
"endLoc": {
"line": 136,
"column": 4,
"position": 1291
}
},
"secondFile": {
"name": "NotificationActionHandler.swift",
"start": 86,
"end": 92,
"startLoc": {
"line": 86,
"column": 7,
"position": 695
},
"endLoc": {
"line": 92,
"column": 4,
"position": 798
}
}
},
{
"format": "swift",
"lines": 13,
"fragment": ", transaction: transaction)\n }\n }.recover(on: .global()) { error -> Promise<Void> in\n Logger.warn(\"Failed to send reply message from notification with error: \\(error)\")\n self.notificationPresenter.notifyForFailedSend(inThread: thread)\n throw error\n }.then(on: .global()) { () -> Promise<Void> in\n self.markMessageAsRead(notificationMessage: notificationMessage)\n }\n }\n }\n\n func showCallLobby",
"tokens": 0,
"firstFile": {
"name": "NotificationActionHandler.swift",
"start": 142,
"end": 154,
"startLoc": {
"line": 142,
"column": 6,
"position": 1383
},
"endLoc": {
"line": 154,
"column": 14,
"position": 1505
}
},
"secondFile": {
"name": "NotificationActionHandler.swift",
"start": 99,
"end": 112,
"startLoc": {
"line": 99,
"column": 7,
"position": 896
},
"endLoc": {
"line": 112,
"column": 11,
"position": 1019
}
}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment