22 Commits

Author SHA1 Message Date
Yagiz e1f382c648 lowercased is fixed for enum raw value 2019-02-27 22:30:39 +03:00
Yagiz f491ca18c7 Merge branch 'develop' of https://github.com/yagiz/Bagel 2019-02-27 22:25:42 +03:00
Yagiz Gurgul 7f21e32853 Merge pull request #34 from swhitty/http-additional-headers
RequestHeaders should be retrieved from the `currentRequest`
2019-02-27 22:19:13 +03:00
Yagiz Gurgul 7acbc6b10c Merge pull request #31 from viktorasl/25-null-json-response-view
Render null value in raw JSON viewer
2019-02-27 22:18:58 +03:00
Yagiz Gurgul 8f30d7c158 Merge pull request #30 from Kamajabu/feature/implementing-method-filter
Implementing additional filters for method and status
2019-02-27 22:18:44 +03:00
Yagiz Gurgul cdb1b5f9a1 Merge pull request #28 from ridvank/update-project-readability
Convert request method to enum to improve project readability
2019-02-27 22:18:26 +03:00
Yagiz Gurgul 5a8283b4e6 Merge pull request #27 from abarisain/carrier_delegate
Add support for a BagelCarrier delegate
2019-02-27 22:18:12 +03:00
Simon Whitty f3b560c926 RequestHeaders should be retrieved from the currentRequest
URLSession provides a mechanism for additional HTTP Header fields to be added to each URLRequest that manages via `URLSessionConfiguration.HTTPAdditionalHeaders`

request headers should be retrieved from the currentRequest of the data task to observer these and other headers that iOS automatically sends.
2019-02-26 22:17:43 +11:00
Viktoras Laukevičius 2352378f67 Render null value in raw JSON viewer 2019-02-23 11:21:36 +02:00
Kamil Buczel 6cbd185ef6 Added addressFilterTerm, methodFilterTerm, statusFilterTerm
Updated filtration
Small refactor
2019-02-20 10:02:31 +01:00
Kamil Buczel 1df2878063 Added
addressFilterTextField: NSTextField!
statusFilterTextField: NSTextField!
methodFilterTextField: NSTextField!

Enum for their tags. Updated controlTextDidChange for multiple textfields. Small refactor
2019-02-20 10:02:08 +01:00
Kamil Buczel e6b7e7c834 Adding additional filters layout 2019-02-20 10:01:18 +01:00
Kamil Buczel 15468adaa4 General refactor 2019-02-19 19:27:45 +01:00
Ridvan Kuccuk 9750d92e7c Convert request method to enum to improve project 2019-02-07 16:38:19 +01:00
Arnaud Barisain-Monrose b52c216a3d Add support for a BagelCarrier delegate
Allows the app to intercept bagel packets right before they are sent.

This allows for:
 - Various data rewriting
 - Filtering
2019-02-06 22:28:17 +01:00
Yagiz Gurgul d350acae64 Merge pull request #19 from Amnell/feature/cURL
Add support for generating cURL representation
2019-02-02 16:18:13 +03:00
Yagiz Gurgul 2cb2afa611 Merge pull request #23 from olejnjak/extension-api-only
Use app extension API only
2019-01-25 14:38:37 +03:00
Jakub Olejník d10ddf680d Use app extension API only 2019-01-25 11:21:33 +01:00
Mathias Amnell a618bae9f0 Add support for generating cURL representation 2019-01-23 20:01:41 +01:00
Yagiz Gurgul e702acf897 update README 2019-01-20 17:52:58 +03:00
Yagiz Gurgul 99754523c7 update README 2019-01-20 17:52:22 +03:00
Yagiz Gurgul 9eb0f916e0 version badge is dynamic 2019-01-20 17:51:26 +03:00
25 changed files with 480 additions and 180 deletions
+3 -3
View File
@@ -5,8 +5,8 @@
<img src="https://img.shields.io/badge/CocoaPods-compatible-4BC51D.svg?style=flat" /></a>
<a href="https://github.com/Carthage/Carthage" alt="Carthage">
<img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" /></a>
<a href="https://github.com/yagiz/Bagel/releases/tag/1.3.1" alt="Version">
<img src="https://img.shields.io/badge/version-1.3.1-blue.svg?style=flat" /></a>
<a href="https://github.com/yagiz/Bagel/releases" alt="Version">
<img src="https://img.shields.io/github/release/yagiz/Bagel.svg" /></a>
</p>
Bagel is a little native iOS network debugger. It's not a proxy debugger so you don't have to mess around with certificates, proxy settings etc. As long as your iOS devices and your Mac are in the same network, you can view the network traffic of your apps seperated by the devices or simulators.
@@ -20,7 +20,7 @@ Bagel is a little native iOS network debugger. It's not a proxy debugger so you
- Build and archive the project.
#### Install iOS Client
#### CocoaPods
```sh
```shhttps://img.shields.io/badge/version-1.3.1-blue.svg?style=flat
pod 'Bagel', '~> 1.3.2'
```
##### Carthage
+6
View File
@@ -34,6 +34,7 @@
3760A47321F1383F004D1E07 /* BagelURLConnectionInjector.m in Sources */ = {isa = PBXBuildFile; fileRef = 3760A45921F1383F004D1E07 /* BagelURLConnectionInjector.m */; };
3760A47421F1383F004D1E07 /* BagelBaseModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 3760A45A21F1383F004D1E07 /* BagelBaseModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
3760A47B21F13A47004D1E07 /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3760A47A21F13A47004D1E07 /* CocoaAsyncSocket.framework */; };
51102CE2220B87290067EB63 /* BagelCarrierDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 51102CE1220B857E0067EB63 /* BagelCarrierDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -66,6 +67,7 @@
3760A45A21F1383F004D1E07 /* BagelBaseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BagelBaseModel.h; sourceTree = "<group>"; };
3760A47521F13872004D1E07 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
3760A47A21F13A47004D1E07 /* CocoaAsyncSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaAsyncSocket.framework; path = Carthage/Build/iOS/CocoaAsyncSocket.framework; sourceTree = SOURCE_ROOT; };
51102CE1220B857E0067EB63 /* BagelCarrierDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BagelCarrierDelegate.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -107,6 +109,7 @@
3760A44A21F1383F004D1E07 /* BagelBaseModel.m */,
3760A45821F1383F004D1E07 /* BagelBrowser.h */,
3760A44C21F1383F004D1E07 /* BagelBrowser.m */,
51102CE1220B857E0067EB63 /* BagelCarrierDelegate.h */,
3760A44621F1383F004D1E07 /* BagelConfiguration.h */,
3760A45621F1383F004D1E07 /* BagelConfiguration.m */,
3760A44321F1383F004D1E07 /* BagelController.h */,
@@ -147,6 +150,7 @@
buildActionMask = 2147483647;
files = (
3760A46F21F1383F004D1E07 /* Bagel.h in Headers */,
51102CE2220B87290067EB63 /* BagelCarrierDelegate.h in Headers */,
3760A45D21F1383F004D1E07 /* BagelController.h in Headers */,
3760A47221F1383F004D1E07 /* BagelBrowser.h in Headers */,
3760A46021F1383F004D1E07 /* BagelConfiguration.h in Headers */,
@@ -364,6 +368,7 @@
3760A43E21F13817004D1E07 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
@@ -394,6 +399,7 @@
3760A43F21F13817004D1E07 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
+36
View File
@@ -0,0 +1,36 @@
//
// Copyright (c) 2018 Bagel (https://github.com/yagiz/Bagel)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "BagelRequestPacket.h"
@protocol BagelCarrierDelegate <NSObject>
@optional
/**
Called right before Bagel sends a request packet to the Mac app.
Allows your delegate to modify the packet on the fly, or abort the operation.
Return a modified request packet, or nil if you want to filter it out.
*/
- (nullable BagelRequestPacket*)bagelCarrierWillSendRequest:(nonnull BagelRequestPacket*)request;
@end
+3
View File
@@ -20,6 +20,7 @@
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "BagelCarrierDelegate.h"
#import "BagelProjectModel.h"
#import "BagelDeviceModel.h"
#import "BagelUtility.h"
@@ -29,6 +30,8 @@
@property (nonatomic, strong) BagelProjectModel* project;
@property (nonatomic, strong) BagelDeviceModel* device;
@property (nonatomic, weak) id<BagelCarrierDelegate> carrierDelegate;
@property (nonatomic) uint16_t netservicePort;
@property (nonatomic, strong) NSString* netserviceType;
@property (nonatomic, strong) NSString* netserviceDomain;
+9
View File
@@ -214,6 +214,15 @@ static NSString* queueId = @"com.yagiz.bagel.injectController";
packet.project = self.configuration.project;
packet.device = self.configuration.device;
id<BagelCarrierDelegate> carrierDelegate = self.configuration.carrierDelegate;
if ([carrierDelegate respondsToSelector:@selector(bagelCarrierWillSendRequest:)]) {
packet = [carrierDelegate bagelCarrierWillSendRequest:packet];
if (packet == nil) {
return;
}
}
[self.browser sendPacket:packet];
}
+2 -2
View File
@@ -86,14 +86,14 @@
if (self.urlSessionTask) {
requestInfo.url = self.urlSessionTask.originalRequest.URL;
requestInfo.requestHeaders = self.self.urlSessionTask.originalRequest.allHTTPHeaderFields;
requestInfo.requestHeaders = self.self.urlSessionTask.currentRequest.allHTTPHeaderFields;
requestInfo.requestBody = self.self.urlSessionTask.originalRequest.HTTPBody;
requestInfo.requestMethod = self.self.urlSessionTask.originalRequest.HTTPMethod;
}else if (self.urlConnection) {
requestInfo.url = self.urlConnection.originalRequest.URL;
requestInfo.requestHeaders = self.self.urlConnection.originalRequest.allHTTPHeaderFields;
requestInfo.requestHeaders = self.self.urlConnection.currentRequest.allHTTPHeaderFields;
requestInfo.requestBody = self.self.urlConnection.originalRequest.HTTPBody;
requestInfo.requestMethod = self.self.urlConnection.originalRequest.HTTPMethod;
+12
View File
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
1191142A21F8B9CB00BFCA48 /* CURLRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1191142921F8B9CB00BFCA48 /* CURLRepresentation.swift */; };
9AAA3A9C54B46F8D2C8DD674 /* Pods_Bagel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00E3BE2EECB0984D92EFCA30 /* Pods_Bagel.framework */; };
BC1F5B37216746D30045C871 /* FontManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC1F5B36216746D30045C871 /* FontManager.swift */; };
BC32643621738AF0006452FE /* KeyValueRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC32643521738AF0006452FE /* KeyValueRepresentation.swift */; };
@@ -114,6 +115,7 @@
/* Begin PBXFileReference section */
00E3BE2EECB0984D92EFCA30 /* Pods_Bagel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Bagel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1191142921F8B9CB00BFCA48 /* CURLRepresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CURLRepresentation.swift; sourceTree = "<group>"; };
BC1F5B36216746D30045C871 /* FontManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontManager.swift; sourceTree = "<group>"; };
BC32643521738AF0006452FE /* KeyValueRepresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueRepresentation.swift; sourceTree = "<group>"; };
BC5E76C8216A64DB000F658D /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
@@ -236,6 +238,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1191142821F8B9AB00BFCA48 /* CURLRepresentation */ = {
isa = PBXGroup;
children = (
1191142921F8B9CB00BFCA48 /* CURLRepresentation.swift */,
);
path = CURLRepresentation;
sourceTree = "<group>";
};
659EF5768D424A8F8EEB1541 /* Frameworks */ = {
isa = PBXGroup;
children = (
@@ -489,6 +499,7 @@
BCEB9AA4217C951C008BBF3C /* ContentRepresentation */ = {
isa = PBXGroup;
children = (
1191142821F8B9AB00BFCA48 /* CURLRepresentation */,
BCEB9AA5217C9532008BBF3C /* ContentRepresentation.swift */,
BCEB9AA9217CB0BB008BBF3C /* OverviewRepresentation */,
BC32643421738AB5006452FE /* ParameterRepresentation */,
@@ -857,6 +868,7 @@
BCFC853021383267001EC6D7 /* ProjectsViewController.swift in Sources */,
BCA60B442162395000B9DCAD /* DevicesViewModel.swift in Sources */,
BC73DFAE215BFB18002E533B /* BagelPublisher.swift in Sources */,
1191142A21F8B9CB00BFCA48 /* CURLRepresentation.swift in Sources */,
BCA60B41216201B900B9DCAD /* BagelConfiguration.swift in Sources */,
BC61DA752162B976000F6D2F /* DetailViewModel.swift in Sources */,
BC9C77B22163897600E8ADE8 /* DataTextViewModel.swift in Sources */,
+1 -1
View File
@@ -11,7 +11,7 @@ import Cocoa
extension Date {
private static let readableFormat = "dd/MM/yyyy HH:mm:ss"
var readble: String {
var readable: String {
return self.format(dateFormat: Date.readableFormat)
}
@@ -13,9 +13,11 @@ class OverviewViewController: BaseViewController {
@IBOutlet var overviewTextView: NSTextView!
@IBOutlet weak var curlButton: NSButton!
@IBOutlet weak var copyToClipboardButton: NSButton!
var viewModel: OverviewViewModel?
private var isCurl: Bool = false
override func setup() {
@@ -32,11 +34,27 @@ class OverviewViewController: BaseViewController {
func refresh() {
self.overviewTextView.textStorage?.setAttributedString(TextStyles.codeAttributedString(string: self.viewModel?.overviewRepresentation?.rawString ?? ""))
if isCurl {
self.overviewTextView.textStorage?.setAttributedString(TextStyles.codeAttributedString(string: self.viewModel?.curlRepresentation?.rawString ?? ""))
curlButton.state = .on
} else {
self.overviewTextView.textStorage?.setAttributedString(TextStyles.codeAttributedString(string: self.viewModel?.overviewRepresentation?.rawString ?? ""))
curlButton.state = .off
}
}
@IBAction func curlButtonAction(_ sender: Any) {
self.isCurl.toggle()
self.refresh()
}
@IBAction func copyButtonAction(_ sender: Any) {
self.viewModel?.copyToClipboard()
if isCurl {
self.viewModel?.copyCURLToClipboard()
} else {
self.viewModel?.copyTextToClipboard()
}
}
}
@@ -12,6 +12,7 @@ class OverviewViewModel: BaseViewModel {
var packet: BagelPacket?
var overviewRepresentation: OverviewRepresentation?
var curlRepresentation: CURLRepresentation?
func register() {
@@ -26,12 +27,17 @@ class OverviewViewModel: BaseViewModel {
if let requestInfo = self.packet?.requestInfo {
self.overviewRepresentation = OverviewRepresentation(requestInfo: requestInfo)
self.curlRepresentation = CURLRepresentation(requestInfo: requestInfo)
}
self.onChange?()
}
func copyToClipboard() {
func copyTextToClipboard() {
self.overviewRepresentation?.copyToClipboard()
}
func copyCURLToClipboard() {
self.curlRepresentation?.copyToClipboard()
}
}
@@ -117,7 +117,7 @@ class DetailViewController: BaseViewController {
self.tabView.selectTabViewItem(at: self.currentDetailType.rawValue)
self.urlTextField.stringValue = self.viewModel?.packet?.requestInfo?.url ?? ""
self.httpMethodTextField.stringValue = self.viewModel?.packet?.requestInfo?.requestMethod ?? ""
self.httpMethodTextField.stringValue = self.viewModel?.packet?.requestInfo?.requestMethod?.rawValue ?? ""
}
func refreshTypeButtons() {
+29 -15
View File
@@ -46,7 +46,7 @@
<fragment content="Test">
<attributes>
<color key="NSColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" size="13" name="DroidSansMono"/>
<font key="NSFont" metaFont="system"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
@@ -207,8 +207,21 @@
<action selector="copyButtonAction:" target="dbv-oR-1ws" id="ZeH-wK-TFV"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ze8-fq-lWt">
<rect key="frame" x="379" y="7" width="36" height="16"/>
<buttonCell key="cell" type="recessed" title="cURL" bezelStyle="recessed" alignment="center" state="on" imageScaling="proportionallyDown" inset="2" id="MSt-7f-JHj">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<color key="contentTintColor" red="0.70980392160000005" green="0.49803921569999998" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<connections>
<action selector="curlButtonAction:" target="dbv-oR-1ws" id="H2c-aD-nWX"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="ze8-fq-lWt" firstAttribute="centerY" secondItem="9zZ-1e-l97" secondAttribute="centerY" id="9Mr-Ib-eBx"/>
<constraint firstItem="U6O-Tm-OuZ" firstAttribute="leading" secondItem="ze8-fq-lWt" secondAttribute="trailing" constant="10" id="pzJ-6j-Rbh"/>
<constraint firstAttribute="trailing" secondItem="U6O-Tm-OuZ" secondAttribute="trailing" constant="10" id="tkO-3l-Gzv"/>
</constraints>
</view>
@@ -241,6 +254,7 @@
</view>
<connections>
<outlet property="copyToClipboardButton" destination="U6O-Tm-OuZ" id="Bis-TZ-SjP"/>
<outlet property="curlButton" destination="ze8-fq-lWt" id="FCG-bS-aGL"/>
<outlet property="overviewTextView" destination="yGA-r3-ock" id="sTN-fX-keW"/>
</connections>
</viewController>
@@ -290,7 +304,7 @@
<fragment content="sad kasd jasj dksad jkasjd jkasdjk asjkd jksadjk asjk djksajk jkdajk jkdsa jkdjk jkas djkkajsa dk">
<attributes>
<color key="NSColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" size="13" name="DroidSansMono"/>
<font key="NSFont" metaFont="system"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
@@ -343,7 +357,7 @@
<rect key="frame" x="0.0" y="12" width="135" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="3SO-nF-Jew">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@@ -370,14 +384,14 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="KeyValueTableCellView" id="Ze5-kZ-luS" customClass="KeyValueTableCellView" customModule="Bagel" customModuleProvider="target">
<rect key="frame" x="138.5" y="1" width="299" height="43"/>
<rect key="frame" x="139" y="1" width="299" height="43"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ll4-xn-DEL">
<rect key="frame" x="0.0" y="12" width="299" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="GJr-nQ-UMJ">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@@ -622,24 +636,24 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mm2-yo-sQB">
<rect key="frame" x="-2" y="319" width="29" height="19"/>
<rect key="frame" x="-2" y="320" width="30" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="GET" id="S1x-ff-DRQ">
<font key="font" size="13" name="EffraMedium-Regular"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box boxType="custom" borderWidth="0.0" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="dHd-eX-X4k" customClass="ContentBar" customModule="Bagel" customModuleProvider="target">
<rect key="frame" x="35" y="313" width="415" height="30"/>
<rect key="frame" x="36" y="313" width="414" height="30"/>
<view key="contentView" id="N8G-6p-Gm5">
<rect key="frame" x="0.0" y="0.0" width="415" height="30"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="30"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="749" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Baz-mg-73Q">
<rect key="frame" x="3" y="6" width="409" height="18"/>
<rect key="frame" x="3" y="6" width="408" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" focusRingType="none" alignment="left" placeholderString="" id="0y6-ve-dir">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
@@ -662,17 +676,17 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VkR-Eh-dut">
<rect key="frame" x="8" y="24" width="43" height="14"/>
<rect key="frame" x="8" y="27" width="47" height="11"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="REQUEST" id="RAI-o2-Cnk">
<font key="font" size="9" name="Effra-Regular"/>
<font key="font" metaFont="miniSystem"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CjX-gd-hJy">
<rect key="frame" x="393" y="24" width="49" height="14"/>
<rect key="frame" x="389" y="27" width="53" height="11"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="RESPONSE" id="To7-5v-rDc">
<font key="font" size="9" name="Effra-Regular"/>
<font key="font" metaFont="miniSystem"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
@@ -11,20 +11,18 @@ import macOSThemeKit
class DatePacketTableCellView: NSTableCellView {
@IBOutlet weak var titleTextField: NSTextField!
@IBOutlet private weak var titleTextField: NSTextField!
var packet: BagelPacket!
{
didSet
{
self.refresh()
var packet: BagelPacket? {
didSet{
guard let packet = packet else { return }
refresh(with: packet)
}
}
func refresh() {
self.titleTextField.textColor = ThemeColor.secondaryLabelColor
self.titleTextField.stringValue = self.packet.requestInfo?.startDate?.readble ?? ""
func refresh(with packet: BagelPacket) {
titleTextField.textColor = ThemeColor.secondaryLabelColor
titleTextField.stringValue = packet.requestInfo?.startDate?.readable ?? ""
}
}
@@ -11,32 +11,36 @@ import macOSThemeKit
class MethodPacketTableCellView: NSTableCellView {
@IBOutlet weak var titleTextField: NSTextField!
@IBOutlet private weak var titleTextField: NSTextField!
var packet: BagelPacket!
{
didSet
{
self.refresh()
var packet: BagelPacket?{
didSet{
guard let packet = packet else { return }
refresh(with: packet)
}
}
func refresh() {
func refresh(with packet: BagelPacket) {
var methodColor = ThemeColor.httpMethodDefaultColor
if self.packet.requestInfo?.requestMethod == "GET" {
methodColor = ThemeColor.httpMethodGetColor
}else if self.packet.requestInfo?.requestMethod == "POST" {
methodColor = ThemeColor.httpMethodPostColor
}else if self.packet.requestInfo?.requestMethod == "PUT" {
methodColor = ThemeColor.httpMethodPutColor
}else if self.packet.requestInfo?.requestMethod == "DELETE" {
methodColor = ThemeColor.httpMethodDeleteColor
if let requestMethod = packet.requestInfo?.requestMethod {
switch requestMethod {
case .get:
methodColor = ThemeColor.httpMethodGetColor
case .put:
methodColor = ThemeColor.httpMethodPutColor
case .post:
methodColor = ThemeColor.httpMethodPostColor
case .delete:
methodColor = ThemeColor.httpMethodDeleteColor
case .head:
break
}
}
self.titleTextField.textColor = methodColor
self.titleTextField.stringValue = self.packet.requestInfo?.requestMethod ?? ""
self.titleTextField.stringValue = packet.requestInfo?.requestMethod?.rawValue ?? ""
}
}
+122 -18
View File
@@ -62,16 +62,23 @@
<rect key="frame" x="1" y="1" width="40" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RPO-QB-zWr">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="RPO-QB-zWr">
<rect key="frame" x="5" y="0.0" width="34" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="etQ-5E-vgp"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="200" id="nCW-um-xTy">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="RPO-QB-zWr" secondAttribute="trailing" constant="3" id="Bl5-Mf-dwQ"/>
<constraint firstItem="RPO-QB-zWr" firstAttribute="leading" secondItem="VPk-w5-xdq" secondAttribute="leading" constant="7" id="YyA-98-4ns"/>
<constraint firstItem="RPO-QB-zWr" firstAttribute="centerY" secondItem="VPk-w5-xdq" secondAttribute="centerY" id="bJ7-DX-WK4"/>
</constraints>
<connections>
<outlet property="titleTextField" destination="RPO-QB-zWr" id="VPe-A4-zOx"/>
</connections>
@@ -94,16 +101,23 @@
<rect key="frame" x="44" y="1" width="52" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9sG-qU-mJh">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="9sG-qU-mJh">
<rect key="frame" x="5" y="0.0" width="46" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="7Bn-Cb-fYk"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="GET" id="Ntk-Pw-UR8">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="9sG-qU-mJh" firstAttribute="centerY" secondItem="eqC-zI-qTu" secondAttribute="centerY" id="NId-x2-FL3"/>
<constraint firstItem="9sG-qU-mJh" firstAttribute="leading" secondItem="eqC-zI-qTu" secondAttribute="leading" constant="7" id="VuC-XE-gYP"/>
<constraint firstAttribute="trailing" secondItem="9sG-qU-mJh" secondAttribute="trailing" constant="3" id="pQk-mB-u44"/>
</constraints>
<connections>
<outlet property="titleTextField" destination="9sG-qU-mJh" id="yHT-2o-p1v"/>
</connections>
@@ -127,16 +141,23 @@
<rect key="frame" x="99" y="1" width="142" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ipb-Zo-mzM">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Ipb-Zo-mzM">
<rect key="frame" x="5" y="2" width="136" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="H8P-2o-QNJ"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="ADt-eY-pVa">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="Ipb-Zo-mzM" secondAttribute="trailing" constant="3" id="RTe-RC-zjX"/>
<constraint firstItem="Ipb-Zo-mzM" firstAttribute="leading" secondItem="gqm-6g-9Tm" secondAttribute="leading" constant="7" id="Yxt-Rz-Fyj"/>
<constraint firstItem="Ipb-Zo-mzM" firstAttribute="top" secondItem="gqm-6g-9Tm" secondAttribute="top" id="sLz-cx-N8s"/>
</constraints>
<connections>
<outlet property="titleTextField" destination="Ipb-Zo-mzM" id="799-wV-bdT"/>
</connections>
@@ -160,16 +181,23 @@
<rect key="frame" x="244" y="1" width="319" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lqc-CZ-vWv">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="lqc-CZ-vWv">
<rect key="frame" x="5" y="2" width="313" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="fbR-A4-8AR"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" sendsActionOnEndEditing="YES" title="Table View Cell" id="j9t-nF-LfF">
<font key="font" size="12" name="DroidSansMono"/>
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="lqc-CZ-vWv" secondAttribute="trailing" constant="3" id="1sE-0a-tGJ"/>
<constraint firstItem="lqc-CZ-vWv" firstAttribute="leading" secondItem="0Hf-Bc-1kK" secondAttribute="leading" constant="7" id="OSr-vD-oKm"/>
<constraint firstItem="lqc-CZ-vWv" firstAttribute="top" secondItem="0Hf-Bc-1kK" secondAttribute="top" id="n3i-Gq-fs0"/>
</constraints>
<connections>
<outlet property="titleTextField" destination="lqc-CZ-vWv" id="1uF-Ck-sP4"/>
</connections>
@@ -218,24 +246,24 @@
</connections>
</button>
<box boxType="custom" borderWidth="0.0" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="ECf-Ip-WqV">
<rect key="frame" x="5" y="5" width="200" height="20"/>
<rect key="frame" x="54" y="5" width="200" height="20"/>
<view key="contentView" id="Vap-9R-hh7">
<rect key="frame" x="0.0" y="0.0" width="200" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Nh8-PV-Qe4">
<rect key="frame" x="3" y="0.0" width="194" height="20"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" placeholderString="Filter" id="OhO-md-Jfb">
<font key="font" size="13" name="Effra-Regular"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" placeholderString="URL..." id="OhO-md-Jfb">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="labelColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="Nh8-PV-Qe4" firstAttribute="leading" secondItem="Vap-9R-hh7" secondAttribute="leading" constant="5" id="6Fu-xV-iMV"/>
<constraint firstItem="Nh8-PV-Qe4" firstAttribute="top" secondItem="Vap-9R-hh7" secondAttribute="top" id="MVc-al-bQg"/>
<constraint firstAttribute="bottom" secondItem="Nh8-PV-Qe4" secondAttribute="bottom" id="OFG-SD-vdg"/>
<constraint firstItem="Nh8-PV-Qe4" firstAttribute="leading" secondItem="Vap-9R-hh7" secondAttribute="leading" constant="5" id="fZy-Mx-aKw"/>
<constraint firstAttribute="trailing" secondItem="Nh8-PV-Qe4" secondAttribute="trailing" constant="5" id="sjk-3w-cno"/>
</constraints>
</view>
@@ -244,11 +272,85 @@
</constraints>
<color key="fillColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</box>
<box boxType="custom" borderWidth="0.0" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="iSU-u4-CHh">
<rect key="frame" x="262" y="5" width="72" height="20"/>
<view key="contentView" id="bTY-Gz-LX8">
<rect key="frame" x="0.0" y="0.0" width="72" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="K4O-j7-3QY">
<rect key="frame" x="3" y="0.0" width="66" height="20"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" placeholderString="Status..." id="phe-Xy-3Ds">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="labelColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="K4O-j7-3QY" firstAttribute="top" secondItem="bTY-Gz-LX8" secondAttribute="top" id="FDv-mK-aCx"/>
<constraint firstAttribute="bottom" secondItem="K4O-j7-3QY" secondAttribute="bottom" id="NLP-tQ-b3h"/>
<constraint firstItem="K4O-j7-3QY" firstAttribute="leading" secondItem="bTY-Gz-LX8" secondAttribute="leading" constant="5" id="jYY-Gr-yNL"/>
<constraint firstAttribute="trailing" secondItem="K4O-j7-3QY" secondAttribute="trailing" constant="5" id="kQY-kN-zBh"/>
</constraints>
</view>
<constraints>
<constraint firstAttribute="width" constant="72" id="4UX-81-bxQ"/>
</constraints>
<color key="fillColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</box>
<box boxType="custom" borderWidth="0.0" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="D6h-Wu-m6x">
<rect key="frame" x="342" y="5" width="72" height="20"/>
<view key="contentView" id="c8Z-eD-ZA3">
<rect key="frame" x="0.0" y="0.0" width="72" height="20"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H4n-d7-YFE">
<rect key="frame" x="3" y="0.0" width="66" height="20"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" placeholderString="Method..." id="OPB-NY-4Xr">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="labelColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="H4n-d7-YFE" firstAttribute="top" secondItem="c8Z-eD-ZA3" secondAttribute="top" id="9y6-Yi-ucB"/>
<constraint firstAttribute="bottom" secondItem="H4n-d7-YFE" secondAttribute="bottom" id="Cyz-B4-rvl"/>
<constraint firstItem="H4n-d7-YFE" firstAttribute="leading" secondItem="c8Z-eD-ZA3" secondAttribute="leading" constant="5" id="h4Y-eh-hvG"/>
<constraint firstAttribute="trailing" secondItem="H4n-d7-YFE" secondAttribute="trailing" constant="5" id="nUm-kG-UZt"/>
</constraints>
</view>
<constraints>
<constraint firstAttribute="width" constant="72" id="VTl-fD-bqE"/>
</constraints>
<color key="fillColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mer-XV-N6Z">
<rect key="frame" x="6" y="5" width="42" height="20"/>
<textFieldCell key="cell" lineBreakMode="clipping" enabled="NO" alignment="left" title="Filters" usesSingleLineMode="YES" id="6LO-kQ-Zld">
<font key="font" metaFont="system"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="ECf-Ip-WqV" firstAttribute="leading" secondItem="dvd-KM-mI8" secondAttribute="leading" constant="5" id="ABc-aZ-M1W"/>
<constraint firstItem="iSU-u4-CHh" firstAttribute="top" secondItem="ECf-Ip-WqV" secondAttribute="top" id="5oz-DR-Sw5"/>
<constraint firstItem="D6h-Wu-m6x" firstAttribute="centerY" secondItem="dvd-KM-mI8" secondAttribute="centerY" id="BZt-2l-JqE"/>
<constraint firstItem="iSU-u4-CHh" firstAttribute="leading" secondItem="ECf-Ip-WqV" secondAttribute="trailing" constant="8" id="CoD-4z-PnH"/>
<constraint firstItem="mer-XV-N6Z" firstAttribute="top" secondItem="Nh8-PV-Qe4" secondAttribute="top" id="DOY-qd-vYV"/>
<constraint firstAttribute="trailing" secondItem="9pa-LD-9G6" secondAttribute="trailing" constant="10" id="I5N-4v-LhZ"/>
<constraint firstItem="mer-XV-N6Z" firstAttribute="bottom" secondItem="Nh8-PV-Qe4" secondAttribute="bottom" id="Qj9-fA-WYv"/>
<constraint firstItem="ECf-Ip-WqV" firstAttribute="leading" secondItem="mer-XV-N6Z" secondAttribute="trailing" constant="8" id="RK9-XR-Ise"/>
<constraint firstItem="mer-XV-N6Z" firstAttribute="centerY" secondItem="dvd-KM-mI8" secondAttribute="centerY" id="RTh-dM-w05"/>
<constraint firstItem="mer-XV-N6Z" firstAttribute="leading" secondItem="dvd-KM-mI8" secondAttribute="leading" constant="8" id="Xcv-L7-Hct"/>
<constraint firstItem="D6h-Wu-m6x" firstAttribute="top" secondItem="iSU-u4-CHh" secondAttribute="top" id="Yvc-7W-bLI"/>
<constraint firstItem="D6h-Wu-m6x" firstAttribute="leading" secondItem="iSU-u4-CHh" secondAttribute="trailing" constant="8" id="aN8-9B-2x0"/>
<constraint firstItem="iSU-u4-CHh" firstAttribute="centerY" secondItem="dvd-KM-mI8" secondAttribute="centerY" id="doj-wZ-8Ip"/>
<constraint firstItem="D6h-Wu-m6x" firstAttribute="bottom" secondItem="iSU-u4-CHh" secondAttribute="bottom" id="id1-Ml-nZr"/>
<constraint firstItem="ECf-Ip-WqV" firstAttribute="top" secondItem="dvd-KM-mI8" secondAttribute="top" constant="5" id="jC1-ca-z56"/>
<constraint firstItem="iSU-u4-CHh" firstAttribute="bottom" secondItem="ECf-Ip-WqV" secondAttribute="bottom" id="qNt-eG-ll1"/>
<constraint firstAttribute="bottom" secondItem="ECf-Ip-WqV" secondAttribute="bottom" constant="5" id="zBj-Zq-CfZ"/>
</constraints>
</view>
@@ -284,8 +386,10 @@
</constraints>
</view>
<connections>
<outlet property="addressFilterTextField" destination="Nh8-PV-Qe4" id="lwy-vX-lgx"/>
<outlet property="clearButton" destination="9pa-LD-9G6" id="IyR-HG-dqR"/>
<outlet property="filterTextField" destination="Nh8-PV-Qe4" id="lwy-vX-lgx"/>
<outlet property="methodFilterTextField" destination="H4n-d7-YFE" id="fPg-CN-Znu"/>
<outlet property="statusFilterTextField" destination="K4O-j7-3QY" id="BGB-aB-n5p"/>
<outlet property="tableView" destination="CKi-fU-sLr" id="v7l-Ps-Ash"/>
</connections>
</viewController>
@@ -10,7 +10,18 @@ import Cocoa
import macOSThemeKit
class PacketsViewController: BaseViewController {
struct TableIdentifiers {
static let statusCode = "statusCode"
static let method = "method"
static let url = "url"
static let date = "date"
}
enum FilterTags: Int {
case address, status, method
}
static var statusColumnWidth = CGFloat(50.0)
static var methodColumnWidth = CGFloat(55.0)
static var dateColumnWidth = CGFloat(150.0)
@@ -20,7 +31,10 @@ class PacketsViewController: BaseViewController {
@IBOutlet weak var clearButton: NSButton!
@IBOutlet weak var tableView: BaseTableView!
@IBOutlet weak var filterTextField: NSTextField!
@IBOutlet weak var addressFilterTextField: NSTextField!
@IBOutlet weak var statusFilterTextField: NSTextField!
@IBOutlet weak var methodFilterTextField: NSTextField!
override func setup() {
@@ -31,133 +45,120 @@ class PacketsViewController: BaseViewController {
self.tableView.backgroundColor = ThemeColor.controlBackgroundColor
self.tableView.gridColor = ThemeColor.gridColor
self.filterTextField.backgroundColor = ThemeColor.controlBackgroundColor
self.filterTextField.delegate = self
setupFilterTextFields()
self.viewModel?.onChange = { [weak self] in
self?.refresh()
}
self.setupTableViewHeaders()
}
private func setupFilterTextFields() {
self.addressFilterTextField.backgroundColor = ThemeColor.controlBackgroundColor
self.addressFilterTextField.tag = FilterTags.address.rawValue
self.addressFilterTextField.delegate = self
self.statusFilterTextField.backgroundColor = ThemeColor.controlBackgroundColor
self.statusFilterTextField.tag = FilterTags.status.rawValue
self.statusFilterTextField.delegate = self
self.methodFilterTextField.backgroundColor = ThemeColor.controlBackgroundColor
self.methodFilterTextField.tag = FilterTags.method.rawValue
self.methodFilterTextField.delegate = self
}
func refresh() {
let isScrolledToBottom = self.isScrolledToBottom()
self.tableView.reloadData()
if let selectedItemIndex = self.viewModel?.selectedItemIndex {
self.tableView.selectRowIndexes(IndexSet(integer: selectedItemIndex), byExtendingSelection: false)
}
if isScrolledToBottom {
if isScrolledToBottom() {
self.scrollToBottom()
}
}
func setupTableViewHeaders() {
for tableColumn in self.tableView.tableColumns {
if tableColumn.identifier.rawValue == "statusCode" {
switch tableColumn.identifier.rawValue {
case TableIdentifiers.statusCode:
tableColumn.headerCell = FlatTableHeaderCell(textCell: "Status")
tableColumn.width = PacketsViewController.statusColumnWidth
}else if tableColumn.identifier.rawValue == "method" {
case TableIdentifiers.method:
tableColumn.headerCell = FlatTableHeaderCell(textCell: "Method")
tableColumn.width = PacketsViewController.methodColumnWidth
}else if tableColumn.identifier.rawValue == "url" {
case TableIdentifiers.url:
tableColumn.headerCell = FlatTableHeaderCell(textCell: "URL")
tableColumn.width = self.view.frame.size.width - PacketsViewController.statusColumnWidth - PacketsViewController.dateColumnWidth - PacketsViewController.methodColumnWidth
}else if tableColumn.identifier.rawValue == "date" {
tableColumn.width = self.view.frame.size.width - PacketsViewController.statusColumnWidth - PacketsViewController.dateColumnWidth - PacketsViewController.methodColumnWidth
case TableIdentifiers.date:
tableColumn.headerCell = FlatTableHeaderCell(textCell: "Date")
tableColumn.width = PacketsViewController.dateColumnWidth
default:
break
}
}
}
@IBAction func clearButtonAction(_ sender: Any) {
self.viewModel?.clearPackets()
}
}
extension PacketsViewController: NSTableViewDelegate, NSTableViewDataSource
{
extension PacketsViewController: NSTableViewDelegate, NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return self.viewModel?.itemCount() ?? 0
}
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
return FlatTableRowView()
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let identifier = tableColumn?.identifier.rawValue else { return nil }
if (tableColumn?.identifier)!.rawValue == "statusCode" {
switch identifier {
case TableIdentifiers.statusCode:
let cell: StatusPacketTableCellView = self.tableView.makeView(withOwner: nil)!
cell.packet = self.viewModel?.item(at: row)
cell.backgroundStyle = .normal
return cell
}else if (tableColumn?.identifier)!.rawValue == "method" {
case TableIdentifiers.method:
let cell: MethodPacketTableCellView = self.tableView.makeView(withOwner: nil)!
cell.packet = self.viewModel?.item(at: row)
cell.backgroundStyle = .normal
return cell
}else if (tableColumn?.identifier)!.rawValue == "url" {
case TableIdentifiers.url:
let cell: URLPacketTableCellView = self.tableView.makeView(withOwner: nil)!
cell.packet = self.viewModel?.item(at: row)
cell.backgroundStyle = .normal
return cell
}else if (tableColumn?.identifier)!.rawValue == "date" {
case TableIdentifiers.date:
let cell: DatePacketTableCellView = self.tableView.makeView(withOwner: nil)!
cell.packet = self.viewModel?.item(at: row)
cell.backgroundStyle = .normal
return cell
default:
return nil
}
return nil
}
func tableViewSelectionDidChange(_ notification: Notification) {
let selectedRow = self.tableView.selectedRow
if selectedRow >= 0 , let item = self.viewModel?.item(at: selectedRow) {
if item !== self.viewModel?.selectedItem {
self.onPacketSelect?(item)
}
}else {
guard selectedRow >= 0, let item = self.viewModel?.item(at: selectedRow) else {
self.onPacketSelect?(nil)
return
}
guard item !== self.viewModel?.selectedItem else { return }
self.onPacketSelect?(item)
}
}
@@ -166,8 +167,18 @@ extension PacketsViewController: NSTableViewDelegate, NSTableViewDataSource
extension PacketsViewController: NSTextFieldDelegate {
func controlTextDidChange(_ obj: Notification) {
guard let tag = (obj.object as? NSTextField)?.tag else { return }
guard let filterTag = FilterTags(rawValue: tag) else { return }
self.viewModel?.filterTerm = self.filterTextField.stringValue
switch filterTag {
case .address:
viewModel?.addressFilterTerm = addressFilterTextField.stringValue
case .method:
viewModel?.methodFilterTerm = methodFilterTextField.stringValue
case .status:
viewModel?.statusFilterTerm = statusFilterTextField.stringValue
}
}
}
@@ -176,17 +187,11 @@ extension PacketsViewController: NSTextFieldDelegate {
extension PacketsViewController {
func isScrolledToBottom() -> Bool {
if self.tableView.enclosingScrollView?.verticalScroller?.floatValue ?? 0 > 0.9 {
return true
}
return false
return tableView.enclosingScrollView?.verticalScroller?.floatValue ?? 0 > 0.9
}
func scrollToBottom() {
self.tableView.scrollToEndOfDocument(nil)
tableView.scrollToEndOfDocument(nil)
}
}
@@ -9,15 +9,31 @@
import Cocoa
class PacketsViewModel: BaseListViewModel<BagelPacket> {
var filterTerm = "" {
var addressFilterTerm = "" {
didSet {
self.refreshItems()
}
}
var methodFilterTerm = "" {
didSet {
self.refreshItems()
}
}
var statusFilterTerm = "" {
didSet {
self.refreshItems()
}
}
private var allPackets: [BagelPacket] {
return BagelController.shared.selectedProjectController?.selectedDeviceController?.packets ?? []
}
func register() {
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshItems), name: BagelNotifications.didGetPacket, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshItems), name: BagelNotifications.didUpdatePacket, object: nil)
@@ -27,46 +43,61 @@ class PacketsViewModel: BaseListViewModel<BagelPacket> {
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshItems), name: BagelNotifications.didSelectDevice, object: nil)
}
var selectedItem: BagelPacket? {
return BagelController.shared.selectedProjectController?.selectedDeviceController?.selectedPacket
}
var selectedItemIndex: Int? {
guard let selectedItem = self.selectedItem else { return nil }
if let selectedItem = self.selectedItem {
return self.items.firstIndex { $0 === selectedItem }
}
return nil
return self.items.firstIndex { $0 === selectedItem }
}
@objc func refreshItems() {
self.filter(items: BagelController.shared.selectedProjectController?.selectedDeviceController?.packets ?? [])
self.onChange?()
items = filter(items: allPackets)
onChange?()
}
func filter(items: [BagelPacket]?) {
func filter(items: [BagelPacket]) -> [BagelPacket] {
var filteredItems = performAddressFiltration(items)
filteredItems = performMethodFiltration(filteredItems)
return performStatusFiltration(filteredItems)
}
func performAddressFiltration(_ items: [BagelPacket]) -> [BagelPacket] {
guard addressFilterTerm.count > 0 else {
return items
}
if let items = items, filterTerm.count > 0 {
self.items = items.filter({ (packet) -> Bool in
return packet.requestInfo?.url?.contains(self.filterTerm) ?? true
})
}else{
self.items = BagelController.shared.selectedProjectController?.selectedDeviceController?.packets ?? []
return items.filter {
$0.requestInfo?.url?.contains(self.addressFilterTerm) ?? true }
}
func performMethodFiltration(_ items: [BagelPacket]) -> [BagelPacket] {
guard methodFilterTerm.count > 0 else {
return items
}
return items.filter
{ $0.requestInfo?.requestMethod?.rawValue.lowercased()
.contains(self.methodFilterTerm.lowercased()) ?? true }
}
func performStatusFiltration(_ items: [BagelPacket]) -> [BagelPacket] {
guard statusFilterTerm.count > 0 else {
return items
}
guard !statusFilterTerm.trimmingCharacters(in: .whitespaces).isEmpty else {
return items.filter { $0.requestInfo?.statusCode?.trimmingCharacters(in: .whitespaces).isEmpty ?? true}
}
return items.filter
{ $0.requestInfo?.statusCode?.contains(self.statusFilterTerm) ?? false
}
}
func clearPackets() {
BagelController.shared.selectedProjectController?.selectedDeviceController?.clear()
self.refreshItems()
}
@@ -11,20 +11,18 @@ import macOSThemeKit
class URLPacketTableCellView: NSTableCellView {
@IBOutlet weak var titleTextField: NSTextField!
@IBOutlet private weak var titleTextField: NSTextField!
var packet: BagelPacket!
{
didSet
{
self.refresh()
var packet: BagelPacket? {
didSet{
guard let packet = packet else { return }
refresh(with: packet)
}
}
func refresh() {
self.titleTextField.textColor = ThemeColor.labelColor
self.titleTextField.stringValue = self.packet.requestInfo?.url ?? ""
func refresh(with packet: BagelPacket) {
titleTextField.textColor = ThemeColor.labelColor
titleTextField.stringValue = packet.requestInfo?.url ?? ""
}
}
@@ -21,11 +21,8 @@ class ProjectsViewController: BaseViewController {
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.backgroundColor = ThemeColor.projectListBackgroundColor
self.viewModel?.onChange = { [weak self] in
self?.refresh()
}
}
@@ -9,7 +9,6 @@
import Cocoa
class BagelPacket: Codable {
var packetId: String?
var requestInfo: BagelRequestInfo?
@@ -8,12 +8,20 @@
import Cocoa
enum RequestMethod: String, Codable {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
case head = "HEAD"
}
class BagelRequestInfo: Codable {
var url: String?
var requestHeaders: [String: String]?
var requestBody: String?
var requestMethod: String?
var requestMethod: RequestMethod?
var responseHeaders: [String: String]?
var responseData: String?
@@ -0,0 +1,52 @@
//
// CURLRepresentation.swift
// Bagel
//
// Created by Mathias Amnell on 2019-01-23.
// Copyright © 2019 Yagiz Lab. All rights reserved.
//
import Cocoa
class CURLRepresentation: ContentRepresentation {
init(requestInfo: BagelRequestInfo?) {
super.init()
if let requestInfo = requestInfo {
self.rawString = requestInfo.curlString
}
}
}
extension BagelRequestInfo {
// Credits to shaps80
// https://gist.github.com/shaps80/ba6a1e2d477af0383e8f19b87f53661d
fileprivate var curlString: String {
guard let url = url else { return "" }
var baseCommand = "curl \(url)"
if requestMethod == .head {
baseCommand += " --head"
}
var command = [baseCommand]
if let method = self.requestMethod, method != .get && method != .head {
command.append("-X \(method)")
}
if let headers = requestHeaders {
for (key, value) in headers where key != "Cookie" {
command.append("-H '\(key): \(value)'")
}
}
if let data = requestBody {
command.append("-d '\(data)'")
}
return command.joined(separator: " \\\n\t")
}
}
@@ -18,7 +18,7 @@ class OverviewRepresentation: ContentRepresentation {
var overviewString = ""
overviewString = overviewString + (requestInfo.requestMethod ?? "")
overviewString = overviewString + (requestInfo.requestMethod?.rawValue ?? "")
overviewString = overviewString + " "
overviewString = overviewString + (requestInfo.url ?? "")
+1 -1
View File
@@ -62,7 +62,7 @@
}
if (value === null) {
return '<li><span class="key">"' + encode(key) + '": </span><span class="null">"' + encode(value) + '"</span></li>';
return '<li><span class="key">"' + encode(key) + '": </span><span class="null">null</span></li>';
}
switch(type){
+1 -1
View File
@@ -17,4 +17,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: ebe70cf0430bb9673b9d2acef3c2a16142460de8
COCOAPODS: 1.6.0.beta.2
COCOAPODS: 1.6.0